diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java index 1a3e476467e..f2bf2b3ccfb 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java @@ -299,6 +299,8 @@ public class WebSocketPolicy */ public void setIdleTimeout(long ms) { + if(ms < -1) return; // no change (likely came from annotation) + boolean dirty = (this.idleTimeout != ms); assertGreaterThan("IdleTimeout",ms,0); this.idleTimeout = ms; @@ -314,6 +316,8 @@ public class WebSocketPolicy */ public void setInputBufferSize(int size) { + if(size < 0) return; // no change (likely came from annotation) + boolean dirty = (this.inputBufferSize != size); assertGreaterThan("InputBufferSize",size,1); this.inputBufferSize = size; @@ -349,6 +353,8 @@ public class WebSocketPolicy */ public void setMaxBinaryMessageSize(int size) { + if(size < 0) return; // no change (likely came from annotation) + boolean dirty = (this.maxBinaryMessageSize != size); assertGreaterThan("MaxBinaryMessageSize",size,1); @@ -385,6 +391,8 @@ public class WebSocketPolicy */ public void setMaxTextMessageSize(int size) { + if(size < 0) return; // no change (likely came from annotation) + boolean dirty = (this.maxTextMessageSize != size); assertGreaterThan("MaxTextMessageSize",size,1); diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java index f8155a7ceff..ca1917a514d 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java @@ -36,42 +36,29 @@ import org.eclipse.jetty.websocket.api.StatusCode; { ElementType.TYPE }) public @interface WebSocket { - /* NOTE TO OTHER DEVELOPERS: - * If you change any of these default values, - * make sure you sync the values with WebSocketPolicy - */ - /** - * The size of the buffer used to read from the network layer. - *

- * Default: 4096 (4 K) + * The size of the buffer (in bytes) used to read from the network layer. */ - int inputBufferSize() default 4 * 1024; + int inputBufferSize() default -2; /** - * The maximum size of a binary message during parsing/generating. + * The maximum size of a binary message (in bytes) during parsing/generating. *

* Binary messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE} - *

- * Default: 65536 (64 K) */ - int maxBinaryMessageSize() default 64 * 1024; + int maxBinaryMessageSize() default -2; /** * The time in ms (milliseconds) that a websocket may be idle before closing. - *

- * Default: 300000 (ms) */ - int maxIdleTime() default 300_000; + int maxIdleTime() default -2; /** * The maximum size of a text message during parsing/generating. *

* Text messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE} - *

- * Default: 65536 (64 K) */ - int maxTextMessageSize() default 64 * 1024; + int maxTextMessageSize() default -2; /** * The output frame buffering mode. diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FunctionCallException.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FunctionCallException.java new file mode 100644 index 00000000000..c5ddf97355c --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FunctionCallException.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 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.common; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.jetty.websocket.api.WebSocketException; + +public class FunctionCallException extends WebSocketException +{ + public FunctionCallException(String message, Throwable cause) + { + super(message, cause); + } + + public FunctionCallException(Throwable cause) + { + super(cause); + } + + public Throwable getInvokedCause() + { + Throwable cause = getCause(); + if (cause instanceof InvocationTargetException) + { + return cause.getCause(); + } + return cause; + } +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java index 89074c925d3..5964b452213 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java @@ -367,6 +367,11 @@ public class Generator } } + public WebSocketBehavior getBehavior() + { + return behavior; + } + public ByteBufferPool getBufferPool() { return bufferPool; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java index 8cc1d553c25..e2281b6ec95 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java @@ -616,8 +616,9 @@ public class Parser buffer.limit(limit); buffer.position(buffer.position() + window.remaining()); - if (LOG.isDebugEnabled()) { - LOG.debug("{} Window: {}",policy.getBehavior(),BufferUtil.toDetailString(window)); + if (LOG.isDebugEnabled()) + { + LOG.debug("{} Raw Payload: {}",policy.getBehavior(),BufferUtil.toDetailString(window)); } maskProcessor.process(window); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java index 459b3c48967..5d48804afad 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java @@ -95,6 +95,7 @@ import org.eclipse.jetty.websocket.common.message.ReaderMessageSink; import org.eclipse.jetty.websocket.common.message.StringMessageSink; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope; +import org.eclipse.jetty.websocket.common.util.DynamicArgsException; import org.eclipse.jetty.websocket.common.util.ReflectUtils; @ManagedObject("A Jetty WebSocket Session") @@ -255,7 +256,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem policy.setMaxBinaryMessageSize(websocket.maxBinaryMessageSize()); policy.setMaxTextMessageSize(websocket.maxTextMessageSize()); policy.setIdleTimeout(websocket.maxIdleTime()); - + this.batchmode = websocket.batchMode(); Method onmethod = null; @@ -511,6 +512,22 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem return connection.getMaxIdleTimeout(); } + private Throwable getInvokedCause(Throwable t) + { + if (t instanceof FunctionCallException) + { + return ((FunctionCallException) t).getInvokedCause(); + } + else if (t instanceof DynamicArgsException) + { + Throwable cause = ((DynamicArgsException) t).getInvokedCause(); + if (cause != null) + return cause; + } + + return t; + } + @Override public InetSocketAddress getLocalAddress() { @@ -692,6 +709,11 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem } } } + else + { + if (LOG.isDebugEnabled()) + LOG.debug("Discarding post EOF frame - {}", frame); + } } catch (NotUtf8Exception e) { @@ -704,25 +726,27 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem } catch (Throwable t) { - LOG.warn("Unhandled Error (closing connection)",t); + Throwable cause = getInvokedCause(t); - notifyError(t); + LOG.warn("Unhandled Error (closing connection)",cause); + + notifyError(cause); // Unhandled Error, close the connection. switch (policy.getBehavior()) { case SERVER: - close(StatusCode.SERVER_ERROR,t.getClass().getSimpleName()); + close(StatusCode.SERVER_ERROR,cause.getClass().getSimpleName()); break; case CLIENT: - close(StatusCode.POLICY_VIOLATION,t.getClass().getSimpleName()); + close(StatusCode.POLICY_VIOLATION,cause.getClass().getSimpleName()); break; } } finally { // Unset active MessageSink if this was a fin frame - if (frame.isFin() && activeMessageSink != null) + if (frame.getType().isData() && frame.isFin() && activeMessageSink != null) activeMessageSink = null; Thread.currentThread().setContextClassLoader(old); @@ -826,7 +850,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem public void open() { if (LOG_OPEN.isDebugEnabled()) - LOG_OPEN.debug("[{}] {}.open()",policy.getBehavior(),this.getClass().getSimpleName()); + LOG_OPEN.debug("[{}] {}.open()", policy.getBehavior(), this.getClass().getSimpleName()); if (remote != null) { @@ -840,9 +864,9 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem connection.getIOState().onConnected(); // Connect remote - remote = new WebSocketRemoteEndpoint(connection,outgoingHandler,getBatchMode()); + remote = new WebSocketRemoteEndpoint(connection, outgoingHandler, getBatchMode()); if (LOG_OPEN.isDebugEnabled()) - LOG_OPEN.debug("[{}] {}.open() remote={}",policy.getBehavior(),this.getClass().getSimpleName(),remote); + LOG_OPEN.debug("[{}] {}.open() remote={}", policy.getBehavior(), this.getClass().getSimpleName(), remote); // Open WebSocket if (onOpenFunction != null) @@ -853,7 +877,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem if (LOG.isDebugEnabled()) { - LOG.debug("open -> {}",dump()); + LOG.debug("open -> {}", dump()); } if(openFuture != null) @@ -864,11 +888,15 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem catch (CloseException ce) { LOG.warn(ce); - close(ce.getStatusCode(),ce.getMessage()); + notifyError(ce.getCause()); + close(ce.getStatusCode(), ce.getMessage()); } catch (Throwable t) { - LOG.warn(t); + Throwable cause = getInvokedCause(t); + + LOG.warn(cause); + notifyError(cause); // Exception on end-user WS-Endpoint. // Fast-fail & close connection with reason. int statusCode = StatusCode.SERVER_ERROR; @@ -876,7 +904,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem { statusCode = StatusCode.POLICY_VIOLATION; } - close(statusCode,t.getMessage()); + close(statusCode,cause.getMessage()); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteArrayFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteArrayFunction.java index fb3e8eef6e2..6b6e6c13c37 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteArrayFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteArrayFunction.java @@ -23,9 +23,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -93,7 +93,7 @@ public class OnByteArrayFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteBufferFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteBufferFunction.java index cdf203e7f4c..e3395cb1011 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteBufferFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnByteBufferFunction.java @@ -24,9 +24,9 @@ import java.nio.ByteBuffer; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -90,7 +90,7 @@ public class OnByteBufferFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnCloseFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnCloseFunction.java index 5621e14bf9b..e23f594c354 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnCloseFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnCloseFunction.java @@ -23,10 +23,10 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.CloseInfo; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -83,7 +83,7 @@ public class OnCloseFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call close method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call close method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnErrorFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnErrorFunction.java index a12222bfa71..a2f8aea562d 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnErrorFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnErrorFunction.java @@ -23,9 +23,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -79,7 +79,7 @@ public class OnErrorFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call error method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call error method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnFrameFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnFrameFunction.java index 6168bedeabd..f5afcaf27ca 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnFrameFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnFrameFunction.java @@ -23,10 +23,10 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.util.DynamicArgs; @@ -82,7 +82,7 @@ public class OnFrameFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call frame method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call frame method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnInputStreamFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnInputStreamFunction.java index 8096a68a7cc..09c397e40cb 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnInputStreamFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnInputStreamFunction.java @@ -24,9 +24,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -91,7 +91,7 @@ public class OnInputStreamFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnOpenFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnOpenFunction.java index d468eab86bf..efd2ee58966 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnOpenFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnOpenFunction.java @@ -23,9 +23,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -76,7 +76,7 @@ public class OnOpenFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnReaderFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnReaderFunction.java index 3d1cc75ec6a..899cda52e9a 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnReaderFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnReaderFunction.java @@ -24,9 +24,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -90,7 +90,7 @@ public class OnReaderFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnTextFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnTextFunction.java index 9b9bd94659a..2b28e026d50 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnTextFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/functions/OnTextFunction.java @@ -23,9 +23,9 @@ import java.lang.reflect.Method; import java.util.function.Function; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.common.FunctionCallException; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.DynamicArgs; import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg; @@ -89,7 +89,7 @@ public class OnTextFunction implements Function } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); + throw new FunctionCallException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e); } return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java index ef28131500e..aca26826cbf 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java @@ -423,7 +423,7 @@ public class FrameFlusher public String toString() { ByteBuffer aggregate = flusher.aggregate; - return String.format("%s[queueSize=%d,aggregateSize=%d,failure=%s]",getClass().getSimpleName(),queue.size(),aggregate == null?0:aggregate.position(), + return String.format("%s[%s,queueSize=%d,aggregateSize=%d,failure=%s]",getClass().getSimpleName(),generator.getBehavior(),queue.size(),aggregate == null?0:aggregate.position(), failure); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java index 3bda276cc59..3d41783aaea 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java @@ -21,11 +21,15 @@ package org.eclipse.jetty.websocket.common.message; import java.nio.ByteBuffer; import java.util.function.Function; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Utf8StringBuilder; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketPolicy; public class StringMessageSink implements MessageSink { + private static final Logger LOG = Log.getLogger(StringMessageSink.class); private final WebSocketPolicy policy; private final Function onMessageFunction; private Utf8StringBuilder utf; @@ -42,33 +46,31 @@ public class StringMessageSink implements MessageSink @Override public void accept(ByteBuffer payload, Boolean fin) { - try + if (payload != null) { - if (payload != null) - { - policy.assertValidTextMessageSize(size + payload.remaining()); - size += payload.remaining(); + policy.assertValidTextMessageSize(size + payload.remaining()); + size += payload.remaining(); - if (utf == null) - utf = new Utf8StringBuilder(1024); + if (utf == null) + utf = new Utf8StringBuilder(1024); - // allow for fast fail of BAD utf (incomplete utf will trigger on messageComplete) - utf.append(payload); - } + if(LOG.isDebugEnabled()) + LOG.debug("Raw Payload {}", BufferUtil.toDetailString(payload)); + + // allow for fast fail of BAD utf (incomplete utf will trigger on messageComplete) + utf.append(payload); } - finally + + if (fin) { - if (fin) - { - // notify event - if (utf != null) - onMessageFunction.apply(utf.toString()); - else - onMessageFunction.apply(""); - // reset - size = 0; - utf = null; - } + // notify event + if (utf != null) + onMessageFunction.apply(utf.toString()); + else + onMessageFunction.apply(""); + // reset + size = 0; + utf = null; } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/DynamicArgsException.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/DynamicArgsException.java index 5a6363e58ea..e200e3688b0 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/DynamicArgsException.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/DynamicArgsException.java @@ -18,16 +18,31 @@ package org.eclipse.jetty.websocket.common.util; +import java.lang.reflect.InvocationTargetException; + @SuppressWarnings("serial") public class DynamicArgsException extends RuntimeException { public DynamicArgsException(String message, Throwable cause) { - super(message,cause); + super(message, cause); } public DynamicArgsException(String message) { super(message); } + + public Throwable getInvokedCause() + { + Throwable cause = getCause(); + if (cause == null) + return null; + + if (cause instanceof InvocationTargetException) + { + return cause.getCause(); + } + return cause; + } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java index 90871f47d11..120a6c447f5 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; @@ -40,14 +41,18 @@ import org.junit.Test; public class IdleTimeoutTest { + @WebSocket(maxIdleTime = 500) + public static class FastTimeoutRFCSocket extends RFCSocket + { + } + @SuppressWarnings("serial") public static class TimeoutServlet extends WebSocketServlet { @Override public void configure(WebSocketServletFactory factory) { - factory.getPolicy().setIdleTimeout(500); - factory.register(RFCSocket.class); + factory.register(FastTimeoutRFCSocket.class); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java index c433d674f12..2b5c9be479c 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java @@ -557,7 +557,7 @@ public class TestABCase5 extends AbstractABCase } /** - * Send text fragmented in 2 packets, with ping between them (framewise) + * Send text fragmented in 2 packets, with ping between them (frame wise) * @throws Exception on test failure */ @Test diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java index e14c96797b1..997110cf903 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java @@ -46,7 +46,7 @@ public class TestABCase6_BadUTF extends AbstractABCase { private static final Logger LOG = Log.getLogger(TestABCase6_BadUTF.class); - @Parameters + @Parameters(name = "{0} - {1}") public static Collection data() { // The various Good UTF8 sequences as a String (hex form) @@ -163,15 +163,13 @@ public class TestABCase6_BadUTF extends AbstractABCase List expect = new ArrayList<>(); expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame()); - try (Fuzzer fuzzer = new Fuzzer(this)) + try (Fuzzer fuzzer = new Fuzzer(this); + StacklessLogging ignored = new StacklessLogging(Parser.class) ) { - try (StacklessLogging supress = new StacklessLogging(Parser.class)) - { - fuzzer.connect(); - fuzzer.setSendMode(Fuzzer.SendMode.BULK); - fuzzer.send(send); - fuzzer.expect(expect); - } + fuzzer.connect(); + fuzzer.setSendMode(Fuzzer.SendMode.BULK); + fuzzer.send(send); + fuzzer.expect(expect); } } }