Merge branch 'jetty-9' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project into jetty-9
This commit is contained in:
commit
a4ef07443a
|
@ -1,43 +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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** WebSocketGenerator.
|
|
||||||
*/
|
|
||||||
public interface WebSocketGenerator
|
|
||||||
{
|
|
||||||
int flush() throws IOException;
|
|
||||||
boolean isBufferEmpty();
|
|
||||||
void addFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException;
|
|
||||||
}
|
|
|
@ -1,275 +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;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.websocket.generator.Generator;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** WebSocketGenerator.
|
|
||||||
* This class generates websocket packets.
|
|
||||||
* It is fully synchronized because it is likely that async
|
|
||||||
* threads will call the addMessage methods while other
|
|
||||||
* threads are flushing the generator.
|
|
||||||
* @deprecated see {@link Generator} replacement
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class WebSocketGeneratorRFC6455 /* implements WebSocketGenerator */
|
|
||||||
{
|
|
||||||
// final private WebSocketBuffers _buffers;
|
|
||||||
// final private EndPoint _endp;
|
|
||||||
private ByteBuffer _buffer;
|
|
||||||
// private final byte[] _mask=new byte[4];
|
|
||||||
private int _m;
|
|
||||||
private boolean _opsent;
|
|
||||||
// private final MaskGen _maskGen;
|
|
||||||
private boolean _closed;
|
|
||||||
|
|
||||||
/* TODO: Migrate to new Jetty9 IO
|
|
||||||
public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp)
|
|
||||||
{
|
|
||||||
_buffers=buffers;
|
|
||||||
_endp=endp;
|
|
||||||
_maskGen=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
|
||||||
{
|
|
||||||
_buffers=buffers;
|
|
||||||
_endp=endp;
|
|
||||||
_maskGen=maskGen;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized ByteBuffer getBuffer()
|
|
||||||
{
|
|
||||||
return _buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Migrate to new Jetty9 IO
|
|
||||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
|
||||||
{
|
|
||||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
|
||||||
|
|
||||||
if (_closed)
|
|
||||||
throw new EofException("Closed");
|
|
||||||
if (opcode==WebSocketConnectionRFC6455.OP_CLOSE)
|
|
||||||
_closed=true;
|
|
||||||
|
|
||||||
boolean mask=_maskGen!=null;
|
|
||||||
|
|
||||||
if (_buffer==null)
|
|
||||||
_buffer=mask?_buffers.getData():_buffers.getDirectBuffer();
|
|
||||||
|
|
||||||
boolean last=WebSocketConnectionRFC6455.isLastFrame(flags);
|
|
||||||
|
|
||||||
int space=mask?14:10;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
opcode = _opsent?WebSocketConnectionRFC6455.OP_CONTINUATION:opcode;
|
|
||||||
opcode=(byte)(((0xf&flags)<<4)+(0xf&opcode));
|
|
||||||
_opsent=true;
|
|
||||||
|
|
||||||
int payload=length;
|
|
||||||
if (payload+space>_buffer.capacity())
|
|
||||||
{
|
|
||||||
// We must fragement, so clear FIN bit
|
|
||||||
opcode=(byte)(opcode&0x7F); // Clear the FIN bit
|
|
||||||
payload=_buffer.capacity()-space;
|
|
||||||
}
|
|
||||||
else if (last)
|
|
||||||
opcode= (byte)(opcode|0x80); // Set the FIN bit
|
|
||||||
|
|
||||||
// ensure there is space for header
|
|
||||||
if (_buffer.space() <= space)
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
if (_buffer.space() <= space)
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the opcode and length
|
|
||||||
if (payload>0xffff)
|
|
||||||
{
|
|
||||||
_buffer.put(new byte[]{
|
|
||||||
opcode,
|
|
||||||
mask?(byte)0xff:(byte)0x7f,
|
|
||||||
(byte)0,
|
|
||||||
(byte)0,
|
|
||||||
(byte)0,
|
|
||||||
(byte)0,
|
|
||||||
(byte)((payload>>24)&0xff),
|
|
||||||
(byte)((payload>>16)&0xff),
|
|
||||||
(byte)((payload>>8)&0xff),
|
|
||||||
(byte)(payload&0xff)});
|
|
||||||
}
|
|
||||||
else if (payload >=0x7e)
|
|
||||||
{
|
|
||||||
_buffer.put(new byte[]{
|
|
||||||
opcode,
|
|
||||||
mask?(byte)0xfe:(byte)0x7e,
|
|
||||||
(byte)(payload>>8),
|
|
||||||
(byte)(payload&0xff)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_buffer.put(new byte[]{
|
|
||||||
opcode,
|
|
||||||
(byte)(mask?(0x80|payload):payload)});
|
|
||||||
}
|
|
||||||
|
|
||||||
// write mask
|
|
||||||
if (mask)
|
|
||||||
{
|
|
||||||
_maskGen.genMask(_mask);
|
|
||||||
_m=0;
|
|
||||||
_buffer.put(_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write payload
|
|
||||||
int remaining = payload;
|
|
||||||
while (remaining > 0)
|
|
||||||
{
|
|
||||||
_buffer.compact();
|
|
||||||
int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
|
|
||||||
|
|
||||||
if (mask)
|
|
||||||
{
|
|
||||||
for (int i=0;i<chunk;i++)
|
|
||||||
_buffer.put((byte)(content[offset+ (payload-remaining)+i]^_mask[+_m++%4]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_buffer.put(content, offset + (payload - remaining), chunk);
|
|
||||||
|
|
||||||
remaining -= chunk;
|
|
||||||
if (_buffer.space() > 0)
|
|
||||||
{
|
|
||||||
// Gently flush the data, issuing a non-blocking write
|
|
||||||
flushBuffer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Forcibly flush the data, issuing a blocking write
|
|
||||||
flush();
|
|
||||||
if (remaining == 0)
|
|
||||||
{
|
|
||||||
// Gently flush the data, issuing a non-blocking write
|
|
||||||
flushBuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset+=payload;
|
|
||||||
length-=payload;
|
|
||||||
}
|
|
||||||
while (length>0);
|
|
||||||
_opsent=!last;
|
|
||||||
|
|
||||||
if (_buffer!=null && _buffer.length()==0)
|
|
||||||
{
|
|
||||||
_buffers.returnBuffer(_buffer);
|
|
||||||
_buffer=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int flushBuffer() throws IOException
|
|
||||||
{
|
|
||||||
if (!_endp.isOpen())
|
|
||||||
throw new EofException();
|
|
||||||
|
|
||||||
if (_buffer!=null)
|
|
||||||
{
|
|
||||||
int flushed=_buffer.hasContent()?_endp.flush(_buffer):0;
|
|
||||||
if (_closed&&_buffer.length()==0)
|
|
||||||
_endp.shutdownOutput();
|
|
||||||
return flushed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int flush() throws IOException
|
|
||||||
{
|
|
||||||
if (_buffer==null)
|
|
||||||
return 0;
|
|
||||||
int result = flushBuffer();
|
|
||||||
|
|
||||||
if (!_endp.isBlocking())
|
|
||||||
{
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
long end=now+_endp.getMaxIdleTime();
|
|
||||||
while (_buffer.length()>0)
|
|
||||||
{
|
|
||||||
boolean ready = _endp.blockWritable(end-now);
|
|
||||||
if (!ready)
|
|
||||||
{
|
|
||||||
now = System.currentTimeMillis();
|
|
||||||
if (now<end)
|
|
||||||
continue;
|
|
||||||
throw new IOException("Write timeout");
|
|
||||||
}
|
|
||||||
|
|
||||||
result += flushBuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_buffer.compact();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean isBufferEmpty()
|
|
||||||
{
|
|
||||||
return _buffer==null || _buffer.length()==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void returnBuffer()
|
|
||||||
{
|
|
||||||
if (_buffer!=null && _buffer.length()==0)
|
|
||||||
{
|
|
||||||
_buffers.returnBuffer(_buffer);
|
|
||||||
_buffer=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
// Do NOT use synchronized (this)
|
|
||||||
// because it's very easy to deadlock when debugging is enabled.
|
|
||||||
// We do a best effort to print the right toString() and that's it.
|
|
||||||
ByteBuffer buffer = _buffer;
|
|
||||||
return String.format("%s@%x closed=%b buffer=%d",
|
|
||||||
getClass().getSimpleName(),
|
|
||||||
hashCode(),
|
|
||||||
_closed,
|
|
||||||
buffer == null ? -1 : buffer.length());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for tagging methods to receive Binary message events.
|
||||||
|
* <p>
|
||||||
|
* Acceptable method patterns.<br>
|
||||||
|
* Note: <code><u>methodName</u></code> can be any name you want to use.
|
||||||
|
* <ol>
|
||||||
|
* <li><code>public void methodName(byte payload[], int offset, int length)</code></li>
|
||||||
|
* <li><code>public void methodName({@link ByteBuffer} payload)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, byte payload[], int offset, int length)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, {@link ByteBuffer} payload)</code></li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.METHOD })
|
||||||
|
public @interface OnWebSocketBinary
|
||||||
|
{
|
||||||
|
/* no config */
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for tagging methods to receive connection close events.
|
||||||
|
* <p>
|
||||||
|
* Acceptable method patterns.<br>
|
||||||
|
* Note: <code>methodName</code> can be any name you want to use.
|
||||||
|
* <ol>
|
||||||
|
* <li><code>public void methodName(int statusCode, String reason)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, int statusCode, String reason)</code></li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.METHOD })
|
||||||
|
public @interface OnWebSocketClose
|
||||||
|
{
|
||||||
|
/* no config */
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for tagging methods to receive connection open events.
|
||||||
|
* <p>
|
||||||
|
* Only 1 acceptable method pattern for this annotation.<br>
|
||||||
|
* Note: <code>methodName</code> can be any name you want to use.
|
||||||
|
* <ol>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn)</code></li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.METHOD })
|
||||||
|
public @interface OnWebSocketConnect
|
||||||
|
{
|
||||||
|
/* no config */
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
|
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (ADVANCED) Annotation for tagging methods to receive frame events.
|
||||||
|
* <p>
|
||||||
|
* Note: any frame derived from {@link BaseFrame} is acceptable to use as the last parameter here.
|
||||||
|
* <p>
|
||||||
|
* Acceptable method patterns.<br>
|
||||||
|
* Note: <code>methodName</code> can be any name you want to use.
|
||||||
|
* <ol>
|
||||||
|
* <li><code>public void methodName({@link BaseFrame} frame)</code></li>
|
||||||
|
* <li><code>public void methodName(BinaryFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(CloseFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(ControlFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(DataFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(PingFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(PongFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName(TextFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, {@link BaseFrame} frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, BinaryFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, CloseFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, ControlFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, DataFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, PingFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, PongFrame frame)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, TextFrame frame)</code></li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.METHOD })
|
||||||
|
public @interface OnWebSocketFrame
|
||||||
|
{
|
||||||
|
/* no config */
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for tagging methods to receive Text message events.
|
||||||
|
* <p>
|
||||||
|
* Acceptable method patterns.<br>
|
||||||
|
* Note: <code>methodName</code> can be any name you want to use.
|
||||||
|
* <ol>
|
||||||
|
* <li><code>public void methodName(String text)</code></li>
|
||||||
|
* <li><code>public void methodName({@link WebSocketConnection} conn, String text)</code></li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.METHOD })
|
||||||
|
public @interface OnWebSocketText
|
||||||
|
{
|
||||||
|
/* no config */
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.eclipse.jetty.websocket.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags a POJO as being a WebSocket class.
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value =
|
||||||
|
{ ElementType.TYPE })
|
||||||
|
public @interface WebSocket
|
||||||
|
{
|
||||||
|
int maxBinarySize() default 8192;
|
||||||
|
|
||||||
|
int maxBufferSize() default 8192;
|
||||||
|
|
||||||
|
int maxTextSize() default 8192;
|
||||||
|
}
|
|
@ -1,163 +0,0 @@
|
||||||
package org.eclipse.jetty.websocket.api;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.Callback;
|
|
||||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
|
||||||
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
|
||||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants for WebSocket protocol as-defined in <a href="https://tools.ietf.org/html/rfc6455">RFC-6455</a>.
|
|
||||||
* <p>
|
|
||||||
* NOTE: Proposed interface for API (not yet settled)
|
|
||||||
*/
|
|
||||||
public interface WebSocket
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Advanced usage, for those interested in flags
|
|
||||||
*/
|
|
||||||
public static interface BinaryFrameListener
|
|
||||||
{
|
|
||||||
void onWebSocketBinary(BinaryFrame frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage.
|
|
||||||
*/
|
|
||||||
public static interface BinaryListener
|
|
||||||
{
|
|
||||||
void onWebSocketBinary(byte buf[], int offset, int len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NIO flavored basic usage.
|
|
||||||
*/
|
|
||||||
public static interface ByteBufferListener
|
|
||||||
{
|
|
||||||
void onWebSocketBinary(ByteBuffer... buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface Connection
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Terminate connection, normally, without a reason.
|
|
||||||
* <p>
|
|
||||||
* Issues a CloseFrame via {@link #write(Object, Callback, BaseFrame...)}
|
|
||||||
*
|
|
||||||
* @TODO: determine contract for dealing with pending incoming frames.
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Terminate connection, with status code.
|
|
||||||
* <p>
|
|
||||||
* Issues a CloseFrame via {@link #write(Object, Callback, BaseFrame...)}
|
|
||||||
*
|
|
||||||
* @param statusCode
|
|
||||||
* the status code
|
|
||||||
* @param reason
|
|
||||||
* the (optional) reason. (can be null for no reason)
|
|
||||||
* @TODO: determine contract for dealing with pending incoming frames.
|
|
||||||
*/
|
|
||||||
void close(int statusCode, String reason);
|
|
||||||
|
|
||||||
String getSubProtocol();
|
|
||||||
|
|
||||||
boolean isOpen();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)}
|
|
||||||
*/
|
|
||||||
void sendBinary(byte[] data, int offset, int length) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)}
|
|
||||||
*/
|
|
||||||
void sendBinary(ByteBuffer buffer) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)}
|
|
||||||
*/
|
|
||||||
void sendBinary(ByteBuffer... buffers) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage, results in non-blocking call to {@link #write(Object, Callback, String...)}
|
|
||||||
*/
|
|
||||||
void sendText(String message) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advanced usage, with callbacks, enters into outgoing queue
|
|
||||||
*/
|
|
||||||
<C> void write(C context, Callback<C> callback, BaseFrame... frames) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advanced usage, with callbacks, enters into outgoing queue
|
|
||||||
*/
|
|
||||||
<C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advanced usage, with callbacks, enters into outgoing queue
|
|
||||||
*/
|
|
||||||
<C> void write(C context, Callback<C> callback, String... messages) throws IOException;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advanced usage, text frame access to flags as well
|
|
||||||
*/
|
|
||||||
public static interface TextFrameListener
|
|
||||||
{
|
|
||||||
void onWebSocketTextFrame(TextFrame frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic usage
|
|
||||||
*/
|
|
||||||
public static interface TextListener
|
|
||||||
{
|
|
||||||
void onWebSocketText(String message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Per <a href="https://tools.ietf.org/html/rfc6455#section-1.3">RFC 6455, section 1.3</a> - Opening Handshake - this version is "13"
|
|
||||||
*/
|
|
||||||
public final static int VERSION = 13;
|
|
||||||
|
|
||||||
void onClose(int statusCode, String reason);
|
|
||||||
|
|
||||||
void onConnect(WebSocket.Connection connection);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation Ideas (Various WebSocket Events):
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* @OnWebSocketHandshake (server side only?)
|
|
||||||
* public void {methodname}(WebSocket.Connection conn)
|
|
||||||
*
|
|
||||||
* @OnWebSocketConnect
|
|
||||||
* public void {methodname}(WebSocket.Connection conn)
|
|
||||||
*
|
|
||||||
* @OnWebSocketDisconnect
|
|
||||||
* public void {methodname}(WebSocket.Connection conn)
|
|
||||||
*
|
|
||||||
* @OnWebSocketFrame(type=CloseFrame.class)
|
|
||||||
* public void {methodname}(CloseFrame frame);
|
|
||||||
* public void {methodname}(WebSocket.Connection conn, CloseFrame frame);
|
|
||||||
*
|
|
||||||
* @OnWebSocketText
|
|
||||||
* public void {methodname}(String text);
|
|
||||||
* public void {methodname}(WebSocket.Connection conn, String text);
|
|
||||||
*
|
|
||||||
* @OnWebSocketBinary
|
|
||||||
* public void {methodname}(byte buf[], int offset, int length);
|
|
||||||
* public void {methodname}(WebSocket.Connection conn, byte buf[], int offset, int length);
|
|
||||||
* public void {methodname}(ByteBuffer buffer);
|
|
||||||
* public void {methodname}(WebSocket.Connection conn, ByteBuffer buffer);
|
|
||||||
*
|
|
||||||
* @OnWebSocketClose
|
|
||||||
* public void {methodnamne}(int statusCode, String reason);
|
|
||||||
* public void {methodnamne}(WebSocket.Connection conn, int statusCode, String reason);
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package org.eclipse.jetty.websocket.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.Callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection interface for WebSocket protocol <a href="https://tools.ietf.org/html/rfc6455">RFC-6455</a>.
|
||||||
|
*/
|
||||||
|
public interface WebSocketConnection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Terminate connection, {@link StatusCode#NORMAL}, without a reason.
|
||||||
|
* <p>
|
||||||
|
* Basic usage: results in an non-blocking async write, then connection close.
|
||||||
|
*/
|
||||||
|
void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate connection, with status code.
|
||||||
|
* <p>
|
||||||
|
* Advanced usage: results in an non-blocking async write, then connection close.
|
||||||
|
*
|
||||||
|
* @param statusCode
|
||||||
|
* the status code
|
||||||
|
* @param reason
|
||||||
|
* the (optional) reason. (can be null for no reason)
|
||||||
|
* @see StatusCode
|
||||||
|
*/
|
||||||
|
void close(int statusCode, String reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the (now read-only) {@link WebSocketPolicy} in use for this connection.
|
||||||
|
*
|
||||||
|
* @return the policy in use
|
||||||
|
*/
|
||||||
|
WebSocketPolicy getPolicy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote Address in use for this connection.
|
||||||
|
*
|
||||||
|
* @return the remote address if available. (situations like mux extension and proxying makes this information unreliable)
|
||||||
|
*/
|
||||||
|
InetAddress getRemoteAddress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the SubProtocol in use for this connection.
|
||||||
|
*
|
||||||
|
* @return the negotiated sub protocol name in use for this connection.
|
||||||
|
*/
|
||||||
|
String getSubProtocol();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple test to see if connection is open (and not closed)
|
||||||
|
*
|
||||||
|
* @return true if connection still open
|
||||||
|
*/
|
||||||
|
boolean isOpen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a binary message.
|
||||||
|
* <p>
|
||||||
|
* Basic usage, results in an non-blocking async write.
|
||||||
|
*/
|
||||||
|
void write(byte[] data, int offset, int length) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a series of binary messages.
|
||||||
|
* <p>
|
||||||
|
* Note: each buffer results in its own binary message frame.
|
||||||
|
* <p>
|
||||||
|
* Basic usage, results in a series of non-blocking async writes.
|
||||||
|
*/
|
||||||
|
void write(ByteBuffer... buffers) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a series of binary messages.
|
||||||
|
* <p>
|
||||||
|
* Note: each buffer results in its own binary message frame.
|
||||||
|
* <p>
|
||||||
|
* Advanced usage, with callbacks, allows for concurrent NIO style results of the entire write operation. (Callback is only called once at the end of
|
||||||
|
* processing all of the buffers)
|
||||||
|
*/
|
||||||
|
<C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a series of text messages.
|
||||||
|
* <p>
|
||||||
|
* Note: each messages results in its own text message frame.
|
||||||
|
* <p>
|
||||||
|
* Advanced usage, with callbacks, allows for concurrent NIO style results of the entire write operation. (Callback is only called once at the end of
|
||||||
|
* processing all of the buffers)
|
||||||
|
*/
|
||||||
|
<C> void write(C context, Callback<C> callback, String... messages) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a text message.
|
||||||
|
* <p>
|
||||||
|
* Basic usage, results in an non-blocking async write.
|
||||||
|
*/
|
||||||
|
void write(String message) throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.eclipse.jetty.websocket.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic WebSocket Listener interface for incoming WebSocket events.
|
||||||
|
*/
|
||||||
|
public interface WebSocketListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A WebSocket binary frame has been received.
|
||||||
|
*
|
||||||
|
* @param payload the raw payload array received
|
||||||
|
* @param offset the offset in the payload array where the data starts
|
||||||
|
* @param len the length of bytes in the payload
|
||||||
|
*/
|
||||||
|
void onWebSocketBinary(byte payload[], int offset, int len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Close Event was received.
|
||||||
|
* <p>
|
||||||
|
* The underlying {@link WebSocketConnection} will be considered closed at this point.
|
||||||
|
*
|
||||||
|
* @param statusCode
|
||||||
|
* the close status code. (See {@link StatusCode})
|
||||||
|
* @param reason
|
||||||
|
* the optional reason for the close.
|
||||||
|
*/
|
||||||
|
void onWebSocketClose(int statusCode, String reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WebSocketConnection has connected successfully and is ready to be used.
|
||||||
|
* <p>
|
||||||
|
* Note: It is a good idea to track this connection as a field in your object so that you can write messages back.
|
||||||
|
*
|
||||||
|
* @param connection
|
||||||
|
* the connection to use to send messages on.
|
||||||
|
*/
|
||||||
|
void onWebSocketConnect(WebSocketConnection connection);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WebSocket exception has occurred.
|
||||||
|
* <p>
|
||||||
|
* Usually this occurs from bad / malformed incoming packets. (example: bad UTF8 data, frames that are too big, violations of the spec)
|
||||||
|
* <p>
|
||||||
|
* This will result in the {@link WebSocketConnection} being closed by the implementing side.
|
||||||
|
* <p>
|
||||||
|
* Note: you will receive no {@link #onWebSocketClose(int, String)} as this condition results in the API calling
|
||||||
|
* {@link WebSocketConnection#close(int, String)} for you.
|
||||||
|
*
|
||||||
|
* @param error
|
||||||
|
* the error that occurred.
|
||||||
|
*/
|
||||||
|
void onWebSocketException(WebSocketException error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WebSocket Text frame was received.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
void onWebSocketText(String message);
|
||||||
|
}
|
|
@ -1,26 +1,281 @@
|
||||||
package org.eclipse.jetty.websocket.ab;
|
package org.eclipse.jetty.websocket.ab;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.StandardByteBufferPool;
|
|
||||||
import org.eclipse.jetty.websocket.ByteBufferAssert;
|
import org.eclipse.jetty.websocket.ByteBufferAssert;
|
||||||
import org.eclipse.jetty.websocket.Debug;
|
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||||
import org.eclipse.jetty.websocket.generator.Generator;
|
import org.eclipse.jetty.websocket.generator.Generator;
|
||||||
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
|
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
|
||||||
import org.eclipse.jetty.websocket.parser.Parser;
|
import org.eclipse.jetty.websocket.parser.Parser;
|
||||||
import org.eclipse.jetty.websocket.parser.TextPayloadParser;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text Message Spec testing the {@link Generator} and {@link Parser}
|
||||||
|
*/
|
||||||
public class ABCase1_1
|
public class ABCase1_1
|
||||||
{
|
{
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
private WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate125ByteTextCase1_1_2()
|
||||||
|
{
|
||||||
|
int length = 125;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7F;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate126ByteTextCase1_1_3()
|
||||||
|
{
|
||||||
|
int length = 126;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
// expected.put((byte)((length>>8) & 0xFF));
|
||||||
|
// expected.put((byte)(length & 0xFF));
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate127ByteTextCase1_1_4()
|
||||||
|
{
|
||||||
|
int length = 127;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
// expected.put((byte)((length>>8) & 0xFF));
|
||||||
|
// expected.put((byte)(length & 0xFF));
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate128ByteTextCase1_1_5()
|
||||||
|
{
|
||||||
|
int length = 128;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
expected.put((byte)(length >> 8));
|
||||||
|
expected.put((byte)(length & 0xFF));
|
||||||
|
// expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate65535ByteTextCase1_1_6()
|
||||||
|
{
|
||||||
|
int length = 65535;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0xff, (byte)0xff });
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate65536ByteTextCase1_1_7()
|
||||||
|
{
|
||||||
|
int length = 65536;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
builder.append("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFrame textFrame = new TextFrame(builder.toString());
|
||||||
|
textFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(length + 16);
|
||||||
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 11);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7F;
|
||||||
|
expected.put(b);
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 });
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateEmptyTextCase1_1_1()
|
public void testGenerateEmptyTextCase1_1_1()
|
||||||
|
@ -30,7 +285,7 @@ public class ABCase1_1
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
Generator generator = new Generator(policy);
|
||||||
ByteBuffer actual = ByteBuffer.allocate(10);
|
ByteBuffer actual = ByteBuffer.allocate(10);
|
||||||
generator.generate(actual, textFrame);
|
generator.generate(actual,textFrame);
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(5);
|
ByteBuffer expected = ByteBuffer.allocate(5);
|
||||||
|
|
||||||
|
@ -44,6 +299,217 @@ public class ABCase1_1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse125ByteTextCase1_1_2()
|
||||||
|
{
|
||||||
|
int length = 125;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7F;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse126ByteTextCase1_1_3()
|
||||||
|
{
|
||||||
|
int length = 126;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse127ByteTextCase1_1_4()
|
||||||
|
{
|
||||||
|
int length = 127;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse128ByteTextCase1_1_5()
|
||||||
|
{
|
||||||
|
int length = 128;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse65535ByteTextCase1_1_6()
|
||||||
|
{
|
||||||
|
// Debug.enableDebugLogging(Parser.class);
|
||||||
|
// Debug.enableDebugLogging(TextPayloadParser.class);
|
||||||
|
|
||||||
|
int length = 65535;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0xff, (byte)0xff });
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||||
|
policy.setMaxTextMessageSize(length);
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse65536ByteTextCase1_1_7()
|
||||||
|
{
|
||||||
|
int length = 65536;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 11);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x81 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7F;
|
||||||
|
expected.put(b);
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 });
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||||
|
policy.setMaxTextMessageSize(length);
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(TextFrame.class,1);
|
||||||
|
|
||||||
|
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseEmptyTextCase1_1_1()
|
public void testParseEmptyTextCase1_1_1()
|
||||||
{
|
{
|
||||||
|
@ -67,469 +533,4 @@ public class ABCase1_1
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",0,pActual.getPayload());
|
ByteBufferAssert.assertSize("TextFrame.payload",0,pActual.getPayload());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate125ByteTextCase1_1_2()
|
|
||||||
{
|
|
||||||
int length = 125;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7F;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse125ByteTextCase1_1_2()
|
|
||||||
{
|
|
||||||
int length = 125;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7F;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate126ByteTextCase1_1_3()
|
|
||||||
{
|
|
||||||
int length = 126;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
//expected.put((byte)((length>>8) & 0xFF));
|
|
||||||
//expected.put((byte)(length & 0xFF));
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse126ByteTextCase1_1_3()
|
|
||||||
{
|
|
||||||
int length = 126;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate127ByteTextCase1_1_4()
|
|
||||||
{
|
|
||||||
int length = 127;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
//expected.put((byte)((length>>8) & 0xFF));
|
|
||||||
//expected.put((byte)(length & 0xFF));
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse127ByteTextCase1_1_4()
|
|
||||||
{
|
|
||||||
int length = 127;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate128ByteTextCase1_1_5()
|
|
||||||
{
|
|
||||||
int length = 128;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
expected.put((byte)(length>>8));
|
|
||||||
expected.put((byte)(length & 0xFF));
|
|
||||||
//expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse128ByteTextCase1_1_5()
|
|
||||||
{
|
|
||||||
int length = 128;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate65535ByteTextCase1_1_6()
|
|
||||||
{
|
|
||||||
int length = 65535;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse65535ByteTextCase1_1_6()
|
|
||||||
{
|
|
||||||
//Debug.enableDebugLogging(Parser.class);
|
|
||||||
//Debug.enableDebugLogging(TextPayloadParser.class);
|
|
||||||
|
|
||||||
int length = 65535;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
|
||||||
policy.setMaxTextMessageSize(length);
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerate65536ByteTextCase1_1_7()
|
|
||||||
{
|
|
||||||
int length = 65536;
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i)
|
|
||||||
{
|
|
||||||
builder.append("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFrame textFrame = new TextFrame(builder.toString());
|
|
||||||
textFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(length+16);
|
|
||||||
generator.generate(actual, textFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 11);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7F;
|
|
||||||
expected.put(b);
|
|
||||||
expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
|
|
||||||
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse65536ByteTextCase1_1_7()
|
|
||||||
{
|
|
||||||
int length = 65536;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 11);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x81 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7F;
|
|
||||||
expected.put(b);
|
|
||||||
expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
|
||||||
policy.setMaxTextMessageSize(length);
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(TextFrame.class,1);
|
|
||||||
|
|
||||||
TextFrame pActual = (TextFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,76 +1,26 @@
|
||||||
package org.eclipse.jetty.websocket.ab;
|
package org.eclipse.jetty.websocket.ab;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.StandardByteBufferPool;
|
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.websocket.ByteBufferAssert;
|
import org.eclipse.jetty.websocket.ByteBufferAssert;
|
||||||
import org.eclipse.jetty.websocket.Debug;
|
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
||||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
|
||||||
import org.eclipse.jetty.websocket.generator.Generator;
|
import org.eclipse.jetty.websocket.generator.Generator;
|
||||||
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
|
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
|
||||||
import org.eclipse.jetty.websocket.parser.Parser;
|
import org.eclipse.jetty.websocket.parser.Parser;
|
||||||
import org.eclipse.jetty.websocket.parser.TextPayloadParser;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary Message Spec testing the {@link Generator} and {@link Parser}
|
||||||
|
*/
|
||||||
public class ABCase1_2
|
public class ABCase1_2
|
||||||
{
|
{
|
||||||
StandardByteBufferPool bufferPool = new StandardByteBufferPool();
|
private WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerateEmptyBinaryCase1_2_1()
|
|
||||||
{
|
|
||||||
BinaryFrame binaryFrame = new BinaryFrame(new byte[]{});
|
|
||||||
binaryFrame.setFin(true);
|
|
||||||
|
|
||||||
Generator generator = new Generator(policy);
|
|
||||||
ByteBuffer actual = ByteBuffer.allocate(32);
|
|
||||||
generator.generate(actual, binaryFrame);
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82, (byte)0x00 });
|
|
||||||
|
|
||||||
actual.flip();
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseEmptyBinaryCase1_2_1()
|
|
||||||
{
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82, (byte)0x00 });
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",0,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate125ByteBinaryCase1_2_2()
|
public void testGenerate125ByteBinaryCase1_2_2()
|
||||||
|
@ -116,39 +66,6 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse125ByteBinaryCase1_2_2()
|
|
||||||
{
|
|
||||||
int length = 125;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7F;
|
|
||||||
expected.put(b);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate126ByteBinaryCase1_2_3()
|
public void testGenerate126ByteBinaryCase1_2_3()
|
||||||
{
|
{
|
||||||
|
@ -197,40 +114,6 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse126ByteBinaryCase1_2_3()
|
|
||||||
{
|
|
||||||
int length = 126;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate127ByteBinaryCase1_2_4()
|
public void testGenerate127ByteBinaryCase1_2_4()
|
||||||
{
|
{
|
||||||
|
@ -279,40 +162,6 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse127ByteBinaryCase1_2_4()
|
|
||||||
{
|
|
||||||
int length = 127;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= length & 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate128ByteBinaryCase1_2_5()
|
public void testGenerate128ByteBinaryCase1_2_5()
|
||||||
{
|
{
|
||||||
|
@ -359,40 +208,6 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse128ByteBinaryCase1_2_5()
|
|
||||||
{
|
|
||||||
int length = 128;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.putShort((short)length);
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate65535ByteBinaryCase1_2_6()
|
public void testGenerate65535ByteBinaryCase1_2_6()
|
||||||
{
|
{
|
||||||
|
@ -437,42 +252,6 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParse65535ByteBinaryCase1_2_6()
|
|
||||||
{
|
|
||||||
int length = 65535;
|
|
||||||
|
|
||||||
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
|
||||||
|
|
||||||
expected.put(new byte[]
|
|
||||||
{ (byte)0x82 });
|
|
||||||
byte b = 0x00; // no masking
|
|
||||||
b |= 0x7E;
|
|
||||||
expected.put(b);
|
|
||||||
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
|
|
||||||
|
|
||||||
for ( int i = 0 ; i < length ; ++i )
|
|
||||||
{
|
|
||||||
expected.put("*".getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
expected.flip();
|
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
|
||||||
policy.setMaxTextMessageSize(length);
|
|
||||||
Parser parser = new Parser(policy);
|
|
||||||
FrameParseCapture capture = new FrameParseCapture();
|
|
||||||
parser.addListener(capture);
|
|
||||||
parser.parse(expected);
|
|
||||||
|
|
||||||
capture.assertNoErrors();
|
|
||||||
capture.assertHasFrame(BinaryFrame.class,1);
|
|
||||||
|
|
||||||
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerate65536ByteBinaryCase1_2_7()
|
public void testGenerate65536ByteBinaryCase1_2_7()
|
||||||
{
|
{
|
||||||
|
@ -518,6 +297,199 @@ public class ABCase1_2
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateEmptyBinaryCase1_2_1()
|
||||||
|
{
|
||||||
|
BinaryFrame binaryFrame = new BinaryFrame(new byte[]{});
|
||||||
|
binaryFrame.setFin(true);
|
||||||
|
|
||||||
|
Generator generator = new Generator(policy);
|
||||||
|
ByteBuffer actual = ByteBuffer.allocate(32);
|
||||||
|
generator.generate(actual, binaryFrame);
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82, (byte)0x00 });
|
||||||
|
|
||||||
|
actual.flip();
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse125ByteBinaryCase1_2_2()
|
||||||
|
{
|
||||||
|
int length = 125;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7F;
|
||||||
|
expected.put(b);
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < length ; ++i )
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse126ByteBinaryCase1_2_3()
|
||||||
|
{
|
||||||
|
int length = 126;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < length ; ++i )
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse127ByteBinaryCase1_2_4()
|
||||||
|
{
|
||||||
|
int length = 127;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= length & 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < length ; ++i )
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse128ByteBinaryCase1_2_5()
|
||||||
|
{
|
||||||
|
int length = 128;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.putShort((short)length);
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < length ; ++i )
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse65535ByteBinaryCase1_2_6()
|
||||||
|
{
|
||||||
|
int length = 65535;
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(length + 5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82 });
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= 0x7E;
|
||||||
|
expected.put(b);
|
||||||
|
expected.put(new byte[]{ (byte)0xff, (byte)0xff});
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < length ; ++i )
|
||||||
|
{
|
||||||
|
expected.put("*".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||||
|
policy.setMaxTextMessageSize(length);
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParse65536ByteBinaryCase1_2_7()
|
public void testParse65536ByteBinaryCase1_2_7()
|
||||||
{
|
{
|
||||||
|
@ -553,4 +525,28 @@ public class ABCase1_2
|
||||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||||
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseEmptyBinaryCase1_2_1()
|
||||||
|
{
|
||||||
|
|
||||||
|
ByteBuffer expected = ByteBuffer.allocate(5);
|
||||||
|
|
||||||
|
expected.put(new byte[]
|
||||||
|
{ (byte)0x82, (byte)0x00 });
|
||||||
|
|
||||||
|
expected.flip();
|
||||||
|
|
||||||
|
Parser parser = new Parser(policy);
|
||||||
|
FrameParseCapture capture = new FrameParseCapture();
|
||||||
|
parser.addListener(capture);
|
||||||
|
parser.parse(expected);
|
||||||
|
|
||||||
|
capture.assertNoErrors();
|
||||||
|
capture.assertHasFrame(BinaryFrame.class,1);
|
||||||
|
|
||||||
|
BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0);
|
||||||
|
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||||
|
ByteBufferAssert.assertSize("BinaryFrame.payload",0,pActual.getPayload());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.websocket.Debug;
|
|
||||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
@ -18,8 +17,6 @@ public class ClosePayloadParserTest
|
||||||
@Test
|
@Test
|
||||||
public void testGameOver()
|
public void testGameOver()
|
||||||
{
|
{
|
||||||
Debug.enableDebugLogging(Parser.class);
|
|
||||||
Debug.enableDebugLogging(ClosePayloadParser.class);
|
|
||||||
String expectedReason = "Game Over";
|
String expectedReason = "Game Over";
|
||||||
|
|
||||||
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
|
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
|
||||||
|
|
|
@ -61,10 +61,10 @@ public class TextPayloadParserTest
|
||||||
|
|
||||||
Assert.assertThat("Must be a long length payload",utf.length,greaterThan(0xFFFF));
|
Assert.assertThat("Must be a long length payload",utf.length,greaterThan(0xFFFF));
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.allocate(utf.length + 10);
|
ByteBuffer buf = ByteBuffer.allocate(utf.length + 32);
|
||||||
buf.put((byte)0x81);
|
buf.put((byte)0x81);
|
||||||
buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 4 byte payload length)
|
buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 8 byte payload length)
|
||||||
buf.putInt(utf.length);
|
buf.putLong(utf.length);
|
||||||
MaskedByteBuffer.putMask(buf);
|
MaskedByteBuffer.putMask(buf);
|
||||||
MaskedByteBuffer.putPayload(buf,utf);
|
MaskedByteBuffer.putPayload(buf,utf);
|
||||||
buf.flip();
|
buf.flip();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue