Merge branch 'jetty-9' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project into jetty-9
This commit is contained in:
commit
7d4da60d05
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>websocket-core</module>
|
<module>websocket-core</module>
|
||||||
<module>websocket-client</module>
|
<!-- <module>websocket-client</module> -->
|
||||||
<module>websocket-server</module>
|
<module>websocket-server</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|
|
@ -3,27 +3,27 @@ package org.eclipse.jetty.websocket.api;
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class CloseException extends WebSocketException
|
public class CloseException extends WebSocketException
|
||||||
{
|
{
|
||||||
private short statusCode;
|
private int statusCode;
|
||||||
|
|
||||||
public CloseException(short closeCode, String message)
|
public CloseException(int closeCode, String message)
|
||||||
{
|
{
|
||||||
super(message);
|
super(message);
|
||||||
this.statusCode = closeCode;
|
this.statusCode = closeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CloseException(short closeCode, String message, Throwable cause)
|
public CloseException(int closeCode, String message, Throwable cause)
|
||||||
{
|
{
|
||||||
super(message,cause);
|
super(message,cause);
|
||||||
this.statusCode = closeCode;
|
this.statusCode = closeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CloseException(short closeCode, Throwable cause)
|
public CloseException(int closeCode, Throwable cause)
|
||||||
{
|
{
|
||||||
super(cause);
|
super(cause);
|
||||||
this.statusCode = closeCode;
|
this.statusCode = closeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getStatusCode()
|
public int getStatusCode()
|
||||||
{
|
{
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,53 +10,53 @@ public class StatusCode
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short NORMAL = 1000;
|
public final static int NORMAL = 1000;
|
||||||
/**
|
/**
|
||||||
* 1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page.
|
* 1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short SHUTDOWN = 1001;
|
public final static int SHUTDOWN = 1001;
|
||||||
/**
|
/**
|
||||||
* 1002 indicates that an endpoint is terminating the connection due to a protocol error.
|
* 1002 indicates that an endpoint is terminating the connection due to a protocol error.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short PROTOCOL = 1002;
|
public final static int PROTOCOL = 1002;
|
||||||
/**
|
/**
|
||||||
* 1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands
|
* 1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands
|
||||||
* only text data MAY send this if it receives a binary message).
|
* only text data MAY send this if it receives a binary message).
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short BAD_DATA = 1003;
|
public final static int BAD_DATA = 1003;
|
||||||
/**
|
/**
|
||||||
* Reserved. The specific meaning might be defined in the future.
|
* Reserved. The specific meaning might be defined in the future.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short UNDEFINED = 1004;
|
public final static int UNDEFINED = 1004;
|
||||||
/**
|
/**
|
||||||
* 1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
* 1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
||||||
* a status code to indicate that no status code was actually present.
|
* a status code to indicate that no status code was actually present.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short NO_CODE = 1005;
|
public final static int NO_CODE = 1005;
|
||||||
/**
|
/**
|
||||||
* 1006 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
* 1006 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
||||||
* a status code to indicate that the connection was closed abnormally, e.g., without sending or receiving a Close control frame.
|
* a status code to indicate that the connection was closed abnormally, e.g., without sending or receiving a Close control frame.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short NO_CLOSE = 1006;
|
public final static int NO_CLOSE = 1006;
|
||||||
/**
|
/**
|
||||||
* 1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the
|
* 1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the
|
||||||
* message (e.g., non-UTF-8 [<a href="https://tools.ietf.org/html/rfc3629">RFC3629</a>] data within a text message).
|
* message (e.g., non-UTF-8 [<a href="https://tools.ietf.org/html/rfc3629">RFC3629</a>] data within a text message).
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short BAD_PAYLOAD = 1007;
|
public final static int BAD_PAYLOAD = 1007;
|
||||||
/**
|
/**
|
||||||
* 1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code
|
* 1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code
|
||||||
* that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the
|
* that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the
|
||||||
|
@ -64,13 +64,13 @@ public class StatusCode
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short POLICY_VIOLATION = 1008;
|
public final static int POLICY_VIOLATION = 1008;
|
||||||
/**
|
/**
|
||||||
* 1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process.
|
* 1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short MESSAGE_TOO_LARGE = 1009;
|
public final static int MESSAGE_TOO_LARGE = 1009;
|
||||||
/**
|
/**
|
||||||
* 1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the
|
* 1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the
|
||||||
* server didn't return them in the response message of the WebSocket handshake. The list of extensions that are needed SHOULD appear in the /reason/ part
|
* server didn't return them in the response message of the WebSocket handshake. The list of extensions that are needed SHOULD appear in the /reason/ part
|
||||||
|
@ -78,18 +78,18 @@ public class StatusCode
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short REQUIRED_EXTENSION = 1010;
|
public final static int REQUIRED_EXTENSION = 1010;
|
||||||
/**
|
/**
|
||||||
* 1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
|
* 1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short SERVER_ERROR = 1011;
|
public final static int SERVER_ERROR = 1011;
|
||||||
/**
|
/**
|
||||||
* 1015 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
* 1015 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting
|
||||||
* a status code to indicate that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).
|
* a status code to indicate that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||||
*/
|
*/
|
||||||
public final static short FAILED_TLS_HANDSHAKE = 1015;
|
public final static int FAILED_TLS_HANDSHAKE = 1015;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ public class WebSocketEventDriver implements Parser.Listener
|
||||||
reason = reason.substring(0,CloseFrame.MAX_REASON);
|
reason = reason.substring(0,CloseFrame.MAX_REASON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.debug("terminateConnection({},{})",statusCode,reason);
|
LOG.debug("terminateConnection({},{})",statusCode,rawreason);
|
||||||
connection.close(statusCode,reason);
|
connection.close(statusCode,reason);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.websocket.api.OpCode;
|
import org.eclipse.jetty.websocket.api.OpCode;
|
||||||
import org.eclipse.jetty.websocket.api.ProtocolException;
|
import org.eclipse.jetty.websocket.api.ProtocolException;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
|
||||||
|
|
||||||
public abstract class ControlFrame extends BaseFrame
|
public abstract class ControlFrame extends BaseFrame
|
||||||
{
|
{
|
||||||
|
@ -40,9 +39,9 @@ public abstract class ControlFrame extends BaseFrame
|
||||||
@Override
|
@Override
|
||||||
public void setPayload(byte[] buf)
|
public void setPayload(byte[] buf)
|
||||||
{
|
{
|
||||||
if ( buf.length > 125 )
|
if (buf.length > MAX_PAYLOAD)
|
||||||
{
|
{
|
||||||
throw new WebSocketException("Control Payloads can not exceed 125 bytes in length.");
|
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
|
||||||
}
|
}
|
||||||
|
|
||||||
super.setPayload(buf);
|
super.setPayload(buf);
|
||||||
|
|
|
@ -17,7 +17,9 @@ import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.FutureCallback;
|
import org.eclipse.jetty.util.FutureCallback;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.api.CloseException;
|
||||||
import org.eclipse.jetty.websocket.api.ExtensionConfig;
|
import org.eclipse.jetty.websocket.api.ExtensionConfig;
|
||||||
|
import org.eclipse.jetty.websocket.api.ProtocolException;
|
||||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
@ -186,6 +188,7 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements
|
||||||
terminateConnection(StatusCode.PROTOCOL,null);
|
terminateConnection(StatusCode.PROTOCOL,null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.parse(buffer);
|
parser.parse(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.OpCode;
|
import org.eclipse.jetty.websocket.api.OpCode;
|
||||||
|
import org.eclipse.jetty.websocket.api.ProtocolException;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||||
|
@ -125,14 +126,14 @@ public class Parser
|
||||||
|
|
||||||
if (opcode.isControlFrame() && !fin)
|
if (opcode.isControlFrame() && !fin)
|
||||||
{
|
{
|
||||||
throw new WebSocketException("Fragmented Control Frame [" + opcode.name() + "]");
|
throw new ProtocolException("Fragmented Control Frame [" + opcode.name() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == OpCode.CONTINUATION)
|
if (opcode == OpCode.CONTINUATION)
|
||||||
{
|
{
|
||||||
if (parser == null)
|
if (parser == null)
|
||||||
{
|
{
|
||||||
throw new WebSocketException("Fragment continuation frame without prior !FIN");
|
throw new ProtocolException("Fragment continuation frame without prior !FIN");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.eclipse.jetty.websocket.parser;
|
package org.eclipse.jetty.websocket.parser;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public class ClosePayloadParserTest
|
||||||
|
|
||||||
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
|
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
|
||||||
ByteBuffer payload = ByteBuffer.allocate(utf.length + 2);
|
ByteBuffer payload = ByteBuffer.allocate(utf.length + 2);
|
||||||
payload.putShort(StatusCode.NORMAL);
|
payload.putChar((char)StatusCode.NORMAL);
|
||||||
payload.put(utf,0,utf.length);
|
payload.put(utf,0,utf.length);
|
||||||
payload.flip();
|
payload.flip();
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class ClosePayloadParserTest
|
||||||
capture.assertNoErrors();
|
capture.assertNoErrors();
|
||||||
capture.assertHasFrame(CloseFrame.class,1);
|
capture.assertHasFrame(CloseFrame.class,1);
|
||||||
CloseFrame close = (CloseFrame)capture.getFrames().get(0);
|
CloseFrame close = (CloseFrame)capture.getFrames().get(0);
|
||||||
Assert.assertThat("CloseFrame.statusCode",(short)close.getStatusCode(),is(StatusCode.NORMAL));
|
Assert.assertThat("CloseFrame.statusCode",close.getStatusCode(),is(StatusCode.NORMAL));
|
||||||
Assert.assertThat("CloseFrame.data",close.getReason(),is(expectedReason));
|
Assert.assertThat("CloseFrame.data",close.getReason(),is(expectedReason));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
package org.eclipse.jetty.websocket.server.ab;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
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.WebSocketAdapter;
|
||||||
|
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||||
|
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||||
|
import org.eclipse.jetty.websocket.frames.PingFrame;
|
||||||
|
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||||
|
import org.eclipse.jetty.websocket.generator.FrameGenerator;
|
||||||
|
import org.eclipse.jetty.websocket.server.SimpleServletServer;
|
||||||
|
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||||
|
import org.eclipse.jetty.websocket.server.WebSocketServlet;
|
||||||
|
import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient;
|
||||||
|
import org.eclipse.jetty.websocket.server.examples.MyEchoServlet;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
public class TestABCase5
|
||||||
|
{
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public static class RFCServlet extends WebSocketServlet
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void registerWebSockets(WebSocketServerFactory factory)
|
||||||
|
{
|
||||||
|
factory.register(RFCSocket.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RFCSocket extends WebSocketAdapter
|
||||||
|
{
|
||||||
|
private static Logger LOG = Log.getLogger(RFCSocket.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWebSocketText(String message)
|
||||||
|
{
|
||||||
|
LOG.debug("onWebSocketText({})",message);
|
||||||
|
// Test the RFC 6455 close code 1011 that should close
|
||||||
|
// trigger a WebSocket server terminated close.
|
||||||
|
if (message.equals("CRASH"))
|
||||||
|
{
|
||||||
|
System.out.printf("Got OnTextMessage");
|
||||||
|
throw new RuntimeException("Something bad happened");
|
||||||
|
}
|
||||||
|
|
||||||
|
// echo the message back.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
getConnection().write(message);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SimpleServletServer server;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void startServer() throws Exception
|
||||||
|
{
|
||||||
|
server = new SimpleServletServer(new MyEchoServlet());
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void stopServer()
|
||||||
|
{
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCase5_1PingIn2Packets() throws Exception
|
||||||
|
{
|
||||||
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf);
|
||||||
|
|
||||||
|
String fragment1 = "fragment1";
|
||||||
|
|
||||||
|
buf.put((byte)(0x00 | OpCode.PING.getCode()));
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= fragment1.length() & 0x7F;
|
||||||
|
buf.put(b);
|
||||||
|
buf.put(fragment1.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf);
|
||||||
|
|
||||||
|
ByteBuffer buf2 = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf2);
|
||||||
|
|
||||||
|
String fragment2 = "fragment2";
|
||||||
|
|
||||||
|
buf2.put((byte)(0x80 | OpCode.PING.getCode()));
|
||||||
|
b = 0x00; // no masking
|
||||||
|
b |= fragment2.length() & 0x7F;
|
||||||
|
buf2.put(b);
|
||||||
|
buf2.put(fragment2.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf2,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf2);
|
||||||
|
|
||||||
|
// Read frame (hopefully text frame)
|
||||||
|
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||||
|
CloseFrame closeFrame = (CloseFrame)frames.remove();
|
||||||
|
Assert.assertThat("CloseFrame.status code",closeFrame.getStatusCode(),is(1002));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCase5_2PongIn2Packets() throws Exception
|
||||||
|
{
|
||||||
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf);
|
||||||
|
|
||||||
|
String fragment1 = "fragment1";
|
||||||
|
|
||||||
|
buf.put((byte)(0x00 | OpCode.PONG.getCode()));
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= fragment1.length() & 0x7F;
|
||||||
|
buf.put(b);
|
||||||
|
buf.put(fragment1.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf);
|
||||||
|
|
||||||
|
ByteBuffer buf2 = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf2);
|
||||||
|
|
||||||
|
String fragment2 = "fragment2";
|
||||||
|
|
||||||
|
buf2.put((byte)(0x80 | OpCode.CONTINUATION.getCode()));
|
||||||
|
b = 0x00; // no masking
|
||||||
|
b |= fragment2.length() & 0x7F;
|
||||||
|
buf2.put(b);
|
||||||
|
buf2.put(fragment2.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf2,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf2);
|
||||||
|
|
||||||
|
// Read frame (hopefully text frame)
|
||||||
|
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||||
|
CloseFrame closeFrame = (CloseFrame)frames.remove();
|
||||||
|
Assert.assertThat("CloseFrame.status code",closeFrame.getStatusCode(),is(1002));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore ("not re-assembling the strings, something odd with echo socket")
|
||||||
|
public void testCase5_3TextIn2Packets() throws Exception
|
||||||
|
{
|
||||||
|
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf);
|
||||||
|
|
||||||
|
String fragment1 = "fragment1";
|
||||||
|
|
||||||
|
buf.put((byte)(0x00 | OpCode.TEXT.getCode()));
|
||||||
|
|
||||||
|
byte b = 0x00; // no masking
|
||||||
|
b |= fragment1.length() & 0x7F;
|
||||||
|
buf.put(b);
|
||||||
|
buf.put(fragment1.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf);
|
||||||
|
|
||||||
|
ByteBuffer buf2 = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||||
|
BufferUtil.clearToFill(buf2);
|
||||||
|
|
||||||
|
String fragment2 = "fragment2";
|
||||||
|
|
||||||
|
buf2.put((byte)(0x80 | OpCode.CONTINUATION.getCode()));
|
||||||
|
b = 0x00; // no masking
|
||||||
|
b |= fragment2.length() & 0x7F;
|
||||||
|
buf2.put(b);
|
||||||
|
buf2.put(fragment2.getBytes());
|
||||||
|
BufferUtil.flipToFlush(buf2,0);
|
||||||
|
|
||||||
|
client.writeRaw(buf2);
|
||||||
|
|
||||||
|
// Read frame (hopefully text frame)
|
||||||
|
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||||
|
TextFrame textFrame = (TextFrame)frames.remove();
|
||||||
|
Assert.assertThat("TextFrame.payload",textFrame.getPayloadUTF8(),is(fragment1 + fragment2));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue