From b0549d8bf974b25a384956f6a95ce2ce78d69996 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 12 Jul 2012 11:21:35 -0700 Subject: [PATCH 1/2] Introducing IncomingFrames and OutgoingFrames interfaces for everything to use, including Extensions --- .../io/WebSocketClientSelectorManager.java | 2 +- .../websocket/api/BadPayloadException.java | 28 ++ .../jetty/websocket/api/Extension.java | 129 +++++++- .../websocket/api/ExtensionRegistry.java | 4 - .../driver/WebSocketEventDriver.java | 46 +-- .../extensions/AbstractExtension.java | 61 ---- .../WebSocketExtensionRegistry.java | 21 +- .../deflate/DeflateFrameExtension.java | 297 +++++++++++------- .../fragment/FragmentExtension.java | 117 ++++--- .../identity/IdentityExtension.java | 28 +- .../jetty/websocket/io/IncomingFrames.java | 14 + .../jetty/websocket/io/OutgoingFrames.java | 11 + .../jetty/websocket/io/RawConnection.java | 6 + .../io/WebSocketAsyncConnection.java | 21 +- .../websocket/protocol/ExtensionConfig.java | 6 + .../jetty/websocket/protocol/Parser.java | 90 +----- .../websocket/protocol/WebSocketFrame.java | 38 ++- .../GeneratorParserRoundtripTest.java | 4 +- .../jetty/websocket/ab/TestABCase1_1.java | 14 +- .../jetty/websocket/ab/TestABCase1_2.java | 14 +- .../jetty/websocket/ab/TestABCase2.java | 10 +- .../jetty/websocket/ab/TestABCase4.java | 8 +- .../jetty/websocket/ab/TestABCase7_3.java | 12 +- .../driver/WebSocketEventDriverTest.java | 22 +- .../protocol/ClosePayloadParserTest.java | 2 +- .../websocket/protocol/FrameParseCapture.java | 20 +- .../jetty/websocket/protocol/ParserTest.java | 2 +- .../protocol/PingPayloadParserTest.java | 2 +- .../protocol/RFC6455ExamplesParserTest.java | 14 +- .../protocol/TextPayloadParserTest.java | 12 +- .../websocket/server/WebSocketHandshake.java | 6 +- .../server/WebSocketServerFactory.java | 43 +-- .../server/handshake/HandshakeHixie76.java | 4 +- .../server/handshake/HandshakeRFC6455.java | 11 +- .../server/IdentityExtensionTest.java | 1 + .../server/WebSocketLoadRFC6455Test.java | 8 +- .../server/blockhead/BlockheadClient.java | 46 +-- .../server/helper/FrameParseCapture.java | 18 +- 38 files changed, 703 insertions(+), 489 deletions(-) create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/BadPayloadException.java delete mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/AbstractExtension.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/IncomingFrames.java create mode 100644 jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/OutgoingFrames.java diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java index d3aba5a87cb..4cf30d360ae 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java @@ -99,7 +99,7 @@ public class WebSocketClientSelectorManager extends SelectorManager WebSocketAsyncConnection connection = new WebSocketAsyncConnection(endPoint,executor,scheduler,policy,bufferPool); endPoint.setAsyncConnection(connection); - connection.getParser().setListener(websocket); + connection.getParser().setIncomingFramesHandler(websocket); // TODO: track open websockets? bind open websocket to connection? diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/BadPayloadException.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/BadPayloadException.java new file mode 100644 index 00000000000..bec695094f7 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/BadPayloadException.java @@ -0,0 +1,28 @@ +package org.eclipse.jetty.websocket.api; + +import org.eclipse.jetty.websocket.extensions.deflate.DeflateFrameExtension; + +/** + * Exception to terminate the connection because it has received data within a frame payload that was not consistent with the requirements of that frame + * payload. (eg: not UTF-8 in a text frame, or a bad data seen in the {@link DeflateFrameExtension}) + * + * @see StatusCode#BAD_PAYLOAD + */ +@SuppressWarnings("serial") +public class BadPayloadException extends CloseException +{ + public BadPayloadException(String message) + { + super(StatusCode.BAD_PAYLOAD,message); + } + + public BadPayloadException(String message, Throwable t) + { + super(StatusCode.BAD_PAYLOAD,message,t); + } + + public BadPayloadException(Throwable t) + { + super(StatusCode.BAD_PAYLOAD,t); + } +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/Extension.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/Extension.java index b1de7a16312..803a8decada 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/Extension.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/Extension.java @@ -15,12 +15,131 @@ //======================================================================== package org.eclipse.jetty.websocket.api; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.websocket.io.IncomingFrames; +import org.eclipse.jetty.websocket.io.OutgoingFrames; import org.eclipse.jetty.websocket.protocol.ExtensionConfig; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; -public interface Extension +public abstract class Extension implements OutgoingFrames, IncomingFrames { - public ExtensionConfig getConfig(); - public String getName(); - public String getParameterizedName(); - public void setConfig(ExtensionConfig config); + private WebSocketPolicy policy; + private ByteBufferPool bufferPool; + private ExtensionConfig config; + private IncomingFrames nextIncomingFrames; + private OutgoingFrames nextOutgoingFrames; + + public ByteBufferPool getBufferPool() + { + return bufferPool; + } + + public ExtensionConfig getConfig() + { + return config; + } + + public String getName() + { + return config.getName(); + } + + public IncomingFrames getNextIncomingFrames() + { + return nextIncomingFrames; + } + + public OutgoingFrames getNextOutgoingFrames() + { + return nextOutgoingFrames; + } + + public String getParameterizedName() + { + return config.getParameterizedName(); + } + + public WebSocketPolicy getPolicy() + { + return policy; + } + + @Override + public void incoming(WebSocketException e) + { + // pass thru, un-modified + nextIncomingFrames.incoming(e); + } + + @Override + public void incoming(WebSocketFrame frame) + { + // pass thru, un-modified + nextIncomingFrames.incoming(frame); + } + + /** + * Convenience method for {@link #getNextIncomingFrames()#incoming(WebSocketException)} + * + * @param e + * the exception to pass to the next input/incoming + */ + public void nextIncoming(WebSocketException e) + { + nextIncomingFrames.incoming(e); + } + + /** + * Convenience method for {@link #getNextIncomingFrames()#incoming(WebSocketFrame)} + * + * @param frame + * the frame to send to the next input/incoming + */ + public void nextIncoming(WebSocketFrame frame) + { + nextIncomingFrames.incoming(frame); + } + + /** + * Convenience method for {@link #getNextOutgoingFrames()#output(WebSocketFrame)} + * + * @param frame + * the frame to send to the next output + */ + public void nextOutput(WebSocketFrame frame) + { + nextOutgoingFrames.output(frame); + } + + @Override + public void output(WebSocketFrame frame) + { + // pass thru, un-modified + nextOutgoingFrames.output(frame); + } + + public void setBufferPool(ByteBufferPool bufferPool) + { + this.bufferPool = bufferPool; + } + + public void setConfig(ExtensionConfig config) + { + this.config = config; + } + + public void setNextIncomingFrames(IncomingFrames nextIncomingFramesHandler) + { + this.nextIncomingFrames = nextIncomingFramesHandler; + } + + public void setNextOutgoingFrames(OutgoingFrames nextOutgoingFramesHandler) + { + this.nextOutgoingFrames = nextOutgoingFramesHandler; + } + + public void setPolicy(WebSocketPolicy policy) + { + this.policy = policy; + } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/ExtensionRegistry.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/ExtensionRegistry.java index 22e9878a69e..ac368810c5f 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/ExtensionRegistry.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/ExtensionRegistry.java @@ -17,8 +17,6 @@ package org.eclipse.jetty.websocket.api; import java.util.Iterator; -import org.eclipse.jetty.websocket.protocol.ExtensionConfig; - public interface ExtensionRegistry extends Iterable> { public boolean isAvailable(String name); @@ -26,8 +24,6 @@ public interface ExtensionRegistry extends Iterable> @Override public Iterator> iterator(); - public Extension newInstance(ExtensionConfig config); - public void register(String name, Class extension); public void unregister(String name); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriver.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriver.java index bc79f32401d..2c6ee8be659 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriver.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriver.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketListener; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.eclipse.jetty.websocket.io.MessageInputStream; import org.eclipse.jetty.websocket.io.MessageReader; import org.eclipse.jetty.websocket.io.RawConnection; @@ -40,7 +41,6 @@ import org.eclipse.jetty.websocket.io.StreamAppender; import org.eclipse.jetty.websocket.protocol.CloseInfo; import org.eclipse.jetty.websocket.protocol.Frame; import org.eclipse.jetty.websocket.protocol.OpCode; -import org.eclipse.jetty.websocket.protocol.Parser; import org.eclipse.jetty.websocket.protocol.WebSocketFrame; /** @@ -51,7 +51,7 @@ import org.eclipse.jetty.websocket.protocol.WebSocketFrame; *

* There will be an instance of the WebSocketEventDriver per connection. */ -public class WebSocketEventDriver implements Parser.Listener +public class WebSocketEventDriver implements IncomingFrames { private static final Logger LOG = Log.getLogger(WebSocketEventDriver.class); private final Object websocket; @@ -109,16 +109,24 @@ public class WebSocketEventDriver implements Parser.Listener return websocket; } - /** - * Internal entry point for connection established - */ - public void onConnect() + @Override + public void incoming(WebSocketException e) { if (LOG.isDebugEnabled()) { - LOG.debug("{}.onConnect()",websocket.getClass().getSimpleName()); + LOG.debug("{}.incoming({})",websocket.getClass().getSimpleName(),e); + } + + if (e instanceof CloseException) + { + CloseException close = (CloseException)e; + terminateConnection(close.getStatusCode(),close.getMessage()); + } + + if (events.onException != null) + { + events.onException.call(websocket,connection,e); } - events.onConnect.call(websocket,connection); } /** @@ -128,7 +136,7 @@ public class WebSocketEventDriver implements Parser.Listener * the frame that appeared */ @Override - public void onFrame(WebSocketFrame frame) + public void incoming(WebSocketFrame frame) { if (LOG.isDebugEnabled()) { @@ -321,24 +329,16 @@ public class WebSocketEventDriver implements Parser.Listener } } - @Override - public void onWebSocketException(WebSocketException e) + /** + * Internal entry point for connection established + */ + public void onConnect() { if (LOG.isDebugEnabled()) { - LOG.debug("{}.onWebSocketException({})",websocket.getClass().getSimpleName(),e); - } - - if (e instanceof CloseException) - { - CloseException close = (CloseException)e; - terminateConnection(close.getStatusCode(),close.getMessage()); - } - - if (events.onException != null) - { - events.onException.call(websocket,connection,e); + LOG.debug("{}.onConnect()",websocket.getClass().getSimpleName()); } + events.onConnect.call(websocket,connection); } /** diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/AbstractExtension.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/AbstractExtension.java deleted file mode 100644 index 7ebe4d01bc9..00000000000 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/AbstractExtension.java +++ /dev/null @@ -1,61 +0,0 @@ -// ======================================================================== -// Copyright 2011-2012 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.extensions; - -import org.eclipse.jetty.websocket.api.Extension; -import org.eclipse.jetty.websocket.protocol.ExtensionConfig; - - -public class AbstractExtension implements Extension -{ - private final ExtensionConfig config; - - public AbstractExtension(String name) - { - this.config = new ExtensionConfig(name); - } - - @Override - public ExtensionConfig getConfig() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getName() - { - return config.getName(); - } - - @Override - public String getParameterizedName() - { - return config.getParameterizedName(); - } - - @Override - public void setConfig(ExtensionConfig config) - { - this.config.init(config); - } - - @Override - public String toString() - { - return getParameterizedName(); - } -} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/WebSocketExtensionRegistry.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/WebSocketExtensionRegistry.java index 45666c4cec9..3d31a02b27d 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/WebSocketExtensionRegistry.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/WebSocketExtensionRegistry.java @@ -21,19 +21,33 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.Extension; import org.eclipse.jetty.websocket.api.ExtensionRegistry; import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.extensions.deflate.DeflateFrameExtension; +import org.eclipse.jetty.websocket.extensions.fragment.FragmentExtension; +import org.eclipse.jetty.websocket.extensions.identity.IdentityExtension; import org.eclipse.jetty.websocket.protocol.ExtensionConfig; public class WebSocketExtensionRegistry implements ExtensionRegistry { private Map> registry; + private WebSocketPolicy policy; + private ByteBufferPool bufferPool; - public WebSocketExtensionRegistry() + public WebSocketExtensionRegistry(WebSocketPolicy policy, ByteBufferPool bufferPool) { - registry = new HashMap>(); + this.policy = policy; + this.bufferPool = bufferPool; + + this.registry = new HashMap<>(); + + this.registry.put("identity",IdentityExtension.class); + this.registry.put("fragment",FragmentExtension.class); + this.registry.put("x-deflate-frame",DeflateFrameExtension.class); } @Override @@ -56,7 +70,6 @@ public class WebSocketExtensionRegistry implements ExtensionRegistry } } - @Override public Extension newInstance(ExtensionConfig config) { if (config == null) @@ -78,6 +91,8 @@ public class WebSocketExtensionRegistry implements ExtensionRegistry { Extension ext = extClass.newInstance(); ext.setConfig(config); + ext.setPolicy(policy); + ext.setBufferPool(bufferPool); return ext; } catch (InstantiationException | IllegalAccessException e) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/deflate/DeflateFrameExtension.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/deflate/DeflateFrameExtension.java index cd5da2cbeb0..c15f8d2308a 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/deflate/DeflateFrameExtension.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/deflate/DeflateFrameExtension.java @@ -15,28 +15,201 @@ //======================================================================== package org.eclipse.jetty.websocket.extensions.deflate; +import java.nio.ByteBuffer; +import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; +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.extensions.AbstractExtension; +import org.eclipse.jetty.websocket.api.BadPayloadException; +import org.eclipse.jetty.websocket.api.Extension; +import org.eclipse.jetty.websocket.api.MessageTooLargeException; +import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.protocol.ExtensionConfig; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; /** * @TODO Implement proposed deflate frame draft */ -public class DeflateFrameExtension extends AbstractExtension +public class DeflateFrameExtension extends Extension { private static final Logger LOG = Log.getLogger(DeflateFrameExtension.class); - private int _minLength=8; - private Deflater _deflater; - private Inflater _inflater; + private int minLength = 8; + private Deflater deflater; + private Inflater inflater; - public DeflateFrameExtension() + // TODO: bring this method into some sort of ProtocolEnforcement class to share with Parser + private void assertSanePayloadLength(WebSocketFrame frame, int len) { - super("x-deflate-frame"); + LOG.debug("Payload Length: " + len); + // Since we use ByteBuffer so often, having lengths over Integer.MAX_VALUE is really impossible. + if (len > Integer.MAX_VALUE) + { + // OMG! Sanity Check! DO NOT WANT! Won't anyone think of the memory! + throw new MessageTooLargeException("[int-sane!] cannot handle payload lengths larger than " + Integer.MAX_VALUE); + } + getPolicy().assertValidPayloadLength(len); + + switch (frame.getOpCode()) + { + case CLOSE: + if (len == 1) + { + throw new ProtocolException("Invalid close frame payload length, [" + len + "]"); + } + // fall thru + case PING: + case PONG: + if (len > WebSocketFrame.MAX_CONTROL_PAYLOAD) + { + throw new ProtocolException("Invalid control frame payload length, [" + len + "] cannot exceed [" + + WebSocketFrame.MAX_CONTROL_PAYLOAD + "]"); + } + break; + } + } + + @Override + public void incoming(WebSocketFrame frame) + { + if (frame.getOpCode().isControlFrame() || !frame.isRsv1()) + { + // Cannot modify incoming control frames or ones with RSV1 set. + super.incoming(frame); + return; + } + + ByteBuffer data = frame.getPayload(); + // first 1 to 8 bytes contains post-inflated payload size. + int uncompressedLength = readUncompresseLength(frame,data); + + // Set the data that is compressed to the inflater + inflater.setInput(BufferUtil.toArray(frame.getPayload())); + + // Establish place for inflated data + byte buf[] = new byte[uncompressedLength]; + try + { + int left = buf.length; + while (inflater.getRemaining() > 0) + { + // TODO: worry about the ByteBuffer.array here?? + int inflated = inflater.inflate(buf,0,left); + if (inflated == 0) + { + throw new DataFormatException("insufficient data"); + } + left -= inflated; + } + + frame.setPayload(buf); + + nextIncoming(frame); + } + catch (DataFormatException e) + { + LOG.warn(e); + throw new BadPayloadException(e); + } + finally + { + // release original buffer (no longer needed) + getBufferPool().release(data); + } + } + + @Override + public void output(WebSocketFrame frame) + { + if (frame.getOpCode().isControlFrame()) + { + // skip, cannot compress control frames. + super.output(frame); + return; + } + + if (frame.getPayloadLength() < minLength) + { + // skip, frame too small to care compressing it. + super.output(frame); + return; + } + + ByteBuffer data = frame.getPayload(); + int length = frame.getPayloadLength(); + + // prepare the uncompressed input + deflater.reset(); + deflater.setInput(BufferUtil.toArray(data)); + deflater.finish(); + + // prepare the output buffer + byte out[] = new byte[length]; + int out_offset = 0; + + // write the uncompressed length + if (length > 0xFF_FF) + { + out[out_offset++] = 0x7F; + out[out_offset++] = (byte)0; + out[out_offset++] = (byte)0; + out[out_offset++] = (byte)0; + out[out_offset++] = (byte)0; + out[out_offset++] = (byte)((length >> 24) & 0xff); + out[out_offset++] = (byte)((length >> 16) & 0xff); + out[out_offset++] = (byte)((length >> 8) & 0xff); + out[out_offset++] = (byte)(length & 0xff); + } + else if (length >= 0x7E) + { + out[out_offset++] = 0x7E; + out[out_offset++] = (byte)(length >> 8); + out[out_offset++] = (byte)(length & 0xff); + } + else + { + out[out_offset++] = (byte)(length & 0x7f); + } + + deflater.deflate(out,out_offset,length - out_offset); + + frame.setPayload(out); + frame.setRsv1(deflater.finished()); + nextOutput(frame); + + // free original data buffer + getBufferPool().release(data); + } + + private int readUncompresseLength(WebSocketFrame frame, ByteBuffer data) + { + int length = data.get(); + int bytes = 0; + if (length == 0x7F) + { + // length 8 bytes (extended payload length) + length = 0; + bytes = 8; + } + else if (length == 0x7F) + { + // length 2 bytes (extended payload length) + length = 0; + bytes = 2; + } + + while (bytes > 0) + { + byte b = data.get(); + length |= (b & 0xFF) << (8 * bytes); + } + + assertSanePayloadLength(frame,length); + + return length; } @Override @@ -44,113 +217,9 @@ public class DeflateFrameExtension extends AbstractExtension { super.setConfig(config); - _minLength = config.getParameter("minLength",_minLength); + minLength = config.getParameter("minLength",minLength); - _deflater = new Deflater(); - _inflater = new Inflater(); + deflater = new Deflater(); + inflater = new Inflater(); } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.AbstractExtension#onFrame(byte, byte, org.eclipse.jetty.io.Buffer) - */ - /* TODO: Migrate to new Jetty9 IO - @Override - public void onFrame(byte flags, byte opcode, ByteBuffer buffer) - { - if (getConnection().isControl(opcode) || !isFlag(flags,1)) - { - super.onFrame(flags,opcode,buffer); - return; - } - - if (buffer.array()==null) - buffer=buffer.asMutableBuffer(); - - int length=0xff&buffer.get(); - if (length>=0x7e) - { - int b=(length==0x7f)?8:2; - length=0; - while(b-->0) - length=0x100*length+(0xff&buffer.get()); - } - - // TODO check a max framesize - - _inflater.setInput(buffer.array(),buffer.getIndex(),buffer.length()); - ByteArrayBuffer buf = new ByteArrayBuffer(length); - try - { - while(_inflater.getRemaining()>0) - { - int inflated=_inflater.inflate(buf.array(),buf.putIndex(),buf.space()); - if (inflated==0) - throw new DataFormatException("insufficient data"); - buf.setPutIndex(buf.putIndex()+inflated); - } - - super.onFrame(clearFlag(flags,1),opcode,buf); - } - catch(DataFormatException e) - { - LOG.warn(e); - getConnection().close(WebSocketConnectionRFC6455.CLOSE_BAD_PAYLOAD,e.toString()); - } - } - */ - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.AbstractExtension#addFrame(byte, byte, byte[], int, int) - */ - /* TODO: Migrate to new Jetty9 IO - @Override - public void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException - { - if (getConnection().isControl(opcode) || length<_minLength) - { - super.addFrame(clearFlag(flags,1),opcode,content,offset,length); - return; - } - - // prepare the uncompressed input - _deflater.reset(); - _deflater.setInput(content,offset,length); - _deflater.finish(); - - // prepare the output buffer - byte[] out= new byte[length]; - int out_offset=0; - - // write the uncompressed length - if (length>0xffff) - { - out[out_offset++]=0x7f; - out[out_offset++]=(byte)0; - out[out_offset++]=(byte)0; - out[out_offset++]=(byte)0; - out[out_offset++]=(byte)0; - out[out_offset++]=(byte)((length>>24)&0xff); - out[out_offset++]=(byte)((length>>16)&0xff); - out[out_offset++]=(byte)((length>>8)&0xff); - out[out_offset++]=(byte)(length&0xff); - } - else if (length >=0x7e) - { - out[out_offset++]=0x7e; - out[out_offset++]=(byte)(length>>8); - out[out_offset++]=(byte)(length&0xff); - } - else - { - out[out_offset++]=(byte)(length&0x7f); - } - - int l = _deflater.deflate(out,out_offset,length-out_offset); - - if (_deflater.finished()) - super.addFrame(setFlag(flags,1),opcode,out,0,l+out_offset); - else - super.addFrame(clearFlag(flags,1),opcode,content,offset,length); - } - */ } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/fragment/FragmentExtension.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/fragment/FragmentExtension.java index d6dfafe2655..32571dc66cb 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/fragment/FragmentExtension.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/fragment/FragmentExtension.java @@ -15,17 +15,83 @@ //======================================================================== package org.eclipse.jetty.websocket.extensions.fragment; -import org.eclipse.jetty.websocket.extensions.AbstractExtension; +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.api.Extension; import org.eclipse.jetty.websocket.protocol.ExtensionConfig; +import org.eclipse.jetty.websocket.protocol.OpCode; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; -public class FragmentExtension extends AbstractExtension +public class FragmentExtension extends Extension { - private int _maxLength=-1; - private int _minFragments=1; + private int maxLength = -1; + private int minFragments = 1; - public FragmentExtension() + @Override + public void output(WebSocketFrame frame) { - super("fragment"); + if (frame.getOpCode().isControlFrame()) + { + // Cannot fragment Control Frames + getNextOutgoingFrames().output(frame); + return; + } + + int fragments = 1; + int length = frame.getPayloadLength(); + + OpCode opcode = frame.getOpCode(); + ByteBuffer payload = frame.getPayload().slice(); + int originalLimit = payload.limit(); + + // break apart payload based on maxLength rules + if (maxLength > 0) + { + while (length > maxLength) + { + fragments++; + + WebSocketFrame frag = new WebSocketFrame(frame); + frag.setOpCode(opcode); + frag.setFin(false); + payload.limit(Math.min(payload.limit() + maxLength,originalLimit)); + frag.setPayload(payload); + + nextOutput(frag); + + length -= maxLength; + opcode = OpCode.CONTINUATION; + } + } + + // break apart payload based on minimum # of fragments + if (fragments < minFragments) + { + int fragmentsLeft = (minFragments - fragments); + int fragLength = length / fragmentsLeft; // equal sized fragments + + while (fragments < minFragments) + { + fragments++; + + WebSocketFrame frag = new WebSocketFrame(frame); + frag.setOpCode(opcode); + frag.setFin(false); + frag.setPayload(payload); + + nextOutput(frag); + length -= fragLength; + opcode = OpCode.CONTINUATION; + } + } + + // output whatever is left + WebSocketFrame frag = new WebSocketFrame(frame); + frag.setOpCode(opcode); + payload.limit(originalLimit); + frag.setPayload(payload); + + nextOutput(frag); } @Override @@ -33,42 +99,7 @@ public class FragmentExtension extends AbstractExtension { super.setConfig(config); - _maxLength = config.getParameter("maxLength",_maxLength); - _minFragments = config.getParameter("minFragments",_minFragments); - + maxLength = config.getParameter("maxLength",maxLength); + minFragments = config.getParameter("minFragments",minFragments); } - - /* TODO: Migrate to new Jetty9 IO - public void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException - { - if (getConnection().isControl(opcode)) - { - super.addFrame(flags,opcode,content,offset,length); - return; - } - - int fragments=1; - - while (_maxLength>0 && length>_maxLength) - { - fragments++; - super.addFrame((byte)(flags&~getConnection().finMask()),opcode,content,offset,_maxLength); - length-=_maxLength; - offset+=_maxLength; - opcode=getConnection().continuationOpcode(); - } - - while (fragments<_minFragments) - { - int frag=length/2; - fragments++; - super.addFrame((byte)(flags&0x7),opcode,content,offset,frag); - length-=frag; - offset+=frag; - opcode=getConnection().continuationOpcode(); - } - - super.addFrame((byte)(flags|getConnection().finMask()),opcode,content,offset,length); - } - */ } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/identity/IdentityExtension.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/identity/IdentityExtension.java index 1307cb7f1d8..e5db0a11ec2 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/identity/IdentityExtension.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/extensions/identity/IdentityExtension.java @@ -15,12 +15,32 @@ //======================================================================== package org.eclipse.jetty.websocket.extensions.identity; -import org.eclipse.jetty.websocket.extensions.AbstractExtension; +import org.eclipse.jetty.util.QuotedStringTokenizer; +import org.eclipse.jetty.websocket.api.Extension; +import org.eclipse.jetty.websocket.protocol.ExtensionConfig; -public class IdentityExtension extends AbstractExtension +public class IdentityExtension extends Extension { - public IdentityExtension() + private String id; + + @Override + public void setConfig(ExtensionConfig config) { - super("identity"); + super.setConfig(config); + StringBuilder s = new StringBuilder(); + s.append(config.getName()); + s.append("["); + for (String param : config.getParameterKeys()) + { + s.append(';').append(param).append('=').append(QuotedStringTokenizer.quoteIfNeeded(config.getParameter(param,""),";=")); + } + s.append("]"); + id = s.toString(); + } + + @Override + public String toString() + { + return id; } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/IncomingFrames.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/IncomingFrames.java new file mode 100644 index 00000000000..4a79af2e42d --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/IncomingFrames.java @@ -0,0 +1,14 @@ +package org.eclipse.jetty.websocket.io; + +import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +/** + * Interface for dealing with Incoming Frames. + */ +public interface IncomingFrames +{ + public void incoming(WebSocketException e); + + public void incoming(WebSocketFrame frame); +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/OutgoingFrames.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/OutgoingFrames.java new file mode 100644 index 00000000000..d9a7b0f2460 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/OutgoingFrames.java @@ -0,0 +1,11 @@ +package org.eclipse.jetty.websocket.io; + +import org.eclipse.jetty.websocket.protocol.WebSocketFrame; + +/** + * Interface for dealing with outgoing frames. + */ +public interface OutgoingFrames +{ + void output(WebSocketFrame frame); +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/RawConnection.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/RawConnection.java index f68cfc48234..ab05e1bd53b 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/RawConnection.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/RawConnection.java @@ -15,11 +15,13 @@ //======================================================================== package org.eclipse.jetty.websocket.io; +import java.io.IOException; import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.websocket.api.WebSocketConnection; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.protocol.Generator; import org.eclipse.jetty.websocket.protocol.Parser; import org.eclipse.jetty.websocket.protocol.WebSocketFrame; @@ -31,6 +33,8 @@ import org.eclipse.jetty.websocket.protocol.WebSocketFrame; */ public interface RawConnection extends WebSocketConnection { + void close() throws IOException; + void complete(FrameBytes frameBytes); void disconnect(boolean onlyOutput); @@ -45,6 +49,8 @@ public interface RawConnection extends WebSocketConnection Parser getParser(); + WebSocketPolicy getPolicy(); + FrameQueue getQueue(); void write(C context, Callback callback, WebSocketFrame frame); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/WebSocketAsyncConnection.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/WebSocketAsyncConnection.java index 079651a567d..f455a6576f8 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/WebSocketAsyncConnection.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/io/WebSocketAsyncConnection.java @@ -46,7 +46,7 @@ import org.eclipse.jetty.websocket.protocol.WebSocketFrame; /** * Provides the implementation of {@link WebSocketConnection} within the framework of the new {@link AsyncConnection} framework of jetty-io */ -public class WebSocketAsyncConnection extends AbstractAsyncConnection implements RawConnection, WebSocketConnection +public class WebSocketAsyncConnection extends AbstractAsyncConnection implements RawConnection, WebSocketConnection, OutgoingFrames { static final Logger LOG = Log.getLogger(WebSocketAsyncConnection.class); private static final ThreadLocal CURRENT_CONNECTION = new ThreadLocal(); @@ -61,17 +61,14 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements CURRENT_CONNECTION.set(connection); } - final ByteBufferPool bufferPool; + private final ByteBufferPool bufferPool; private final ScheduledExecutorService scheduler; - final Generator generator; + private final Generator generator; private final Parser parser; - final WebSocketPolicy policy; - final FrameQueue queue; - - // TODO: track extensions? (only those that need to operate at this level?) - // TODO: are extensions going to layer the endpoint? - // TODO: are extensions going to layer the connection? + private final WebSocketPolicy policy; + private final FrameQueue queue; private List extensions; + private OutgoingFrames outgoingFramesHandler; private boolean flushing; public WebSocketAsyncConnection(AsyncEndPoint endp, Executor executor, ScheduledExecutorService scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool) @@ -268,6 +265,12 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements fillInterested(); } + @Override + public void output(WebSocketFrame frame) + { + // TODO Auto-generated method stub + } + @Override public void ping(C context, Callback callback, byte[] payload) throws IOException { diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/ExtensionConfig.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/ExtensionConfig.java index e8fb2d3926f..ea45d8f7fea 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/ExtensionConfig.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/ExtensionConfig.java @@ -17,6 +17,7 @@ package org.eclipse.jetty.websocket.protocol; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.eclipse.jetty.util.QuotedStringTokenizer; @@ -85,6 +86,11 @@ public class ExtensionConfig return str.toString(); } + public Set getParameterKeys() + { + return parameters.keySet(); + } + /** * Initialize the parameters on this config from the other configuration. * @param other the other configuration. diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java index 591535d5135..2ed4f647140 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java @@ -16,9 +16,6 @@ package org.eclipse.jetty.websocket.protocol; import java.nio.ByteBuffer; -import java.util.EventListener; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; @@ -27,68 +24,13 @@ import org.eclipse.jetty.websocket.api.MessageTooLargeException; import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.io.IncomingFrames; /** * Parsing of a frames in WebSocket land. */ public class Parser { - public static interface Listener extends EventListener - { - public void onFrame(final WebSocketFrame frame); - - public void onWebSocketException(WebSocketException e); - } - - public static class ListenerList implements Listener - { - private final List listeners = new CopyOnWriteArrayList<>(); - - public void addListener(Listener listener) - { - listeners.add(listener); - } - - @Override - public void onFrame(WebSocketFrame frame) - { - for (Listener listener : listeners) - { - try - { - listener.onFrame(frame); - } - catch (WebSocketException e) - { - throw e; - } - catch (Throwable t) - { - throw new WebSocketException(t); - } - } - } - - @Override - public void onWebSocketException(WebSocketException e) - { - for (Listener listener : listeners) - { - listener.onWebSocketException(e); - } - } - - public void removeListener(Listener listener) - { - listeners.remove(listener); - } - - public void setListeners(List lsnrs) - { - listeners.addAll(lsnrs); - } - } - private enum State { START, @@ -110,7 +52,7 @@ public class Parser private int payloadLength; private static final Logger LOG = Log.getLogger(Parser.class); - private Listener listener; + private IncomingFrames incomingFramesHandler; private WebSocketPolicy policy; public Parser(WebSocketPolicy wspolicy) @@ -136,14 +78,14 @@ public class Parser switch (frame.getOpCode()) { case CLOSE: - if (payloadLength == 1) + if (len == 1) { throw new ProtocolException("Invalid close frame payload length, [" + payloadLength + "]"); } // fall thru case PING: case PONG: - if (payloadLength > WebSocketFrame.MAX_CONTROL_PAYLOAD) + if (len > WebSocketFrame.MAX_CONTROL_PAYLOAD) { throw new ProtocolException("Invalid control frame payload length, [" + payloadLength + "] cannot exceed [" + WebSocketFrame.MAX_CONTROL_PAYLOAD + "]"); @@ -187,9 +129,9 @@ public class Parser return amt; } - public Listener getListener() + public IncomingFrames getIncomingFramesHandler() { - return listener; + return incomingFramesHandler; } public WebSocketPolicy getPolicy() @@ -200,13 +142,13 @@ public class Parser protected void notifyFrame(final WebSocketFrame f) { LOG.debug("Notify Frame: {}",f); - if (listener == null) + if (incomingFramesHandler == null) { return; } try { - listener.onFrame(f); + incomingFramesHandler.incoming(f); } catch (WebSocketException e) { @@ -222,11 +164,11 @@ public class Parser protected void notifyWebSocketException(WebSocketException e) { LOG.debug(e); - if (listener == null) + if (incomingFramesHandler == null) { return; } - listener.onWebSocketException(e); + incomingFramesHandler.incoming(e); } public void parse(ByteBuffer buffer) @@ -345,7 +287,7 @@ public class Parser frame.setMasked((b & 0x80) != 0); payloadLength = (byte)(0x7F & b); - if (payloadLength == 127) + if (payloadLength == 127) // 0x7F { // length 8 bytes (extended payload length) payloadLength = 0; @@ -353,7 +295,7 @@ public class Parser cursor = 8; break; // continue onto next state } - else if (payloadLength == 126) + else if (payloadLength == 126) // 0x7E { // length 2 bytes (extended payload length) payloadLength = 0; @@ -505,16 +447,18 @@ public class Parser return false; } - public void setListener(Listener listener) + public void setIncomingFramesHandler(IncomingFrames incoming) { - this.listener = listener; + this.incomingFramesHandler = incoming; } @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("Parser [state="); + builder.append("Parser ["); + builder.append(incomingFramesHandler.getClass().getSimpleName()); + builder.append(", state="); builder.append(state); builder.append(", cursor="); builder.append(cursor); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/WebSocketFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/WebSocketFrame.java index d3fce4050fb..2dcd1601bb9 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/WebSocketFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/WebSocketFrame.java @@ -87,10 +87,13 @@ public class WebSocketFrame implements Frame private OpCode opcode = null; private boolean masked = false; private byte mask[]; + /** + * The payload data. + *

+ * It is assumed to always be in FLUSH mode (ready to read) in this object. + */ private ByteBuffer data; - private boolean continuation = false; - private int continuationIndex = 0; /** @@ -110,6 +113,33 @@ public class WebSocketFrame implements Frame this.opcode = opcode; } + /** + * Copy constructor for the websocket frame. + *

+ * Note: the underlying payload is merely a {@link ByteBuffer#slice()} of the input frame. + * + * @param copy + * the websocket to copy. + */ + public WebSocketFrame(WebSocketFrame copy) + { + fin = copy.rsv1; + rsv1 = copy.rsv2; + rsv2 = copy.rsv2; + rsv3 = copy.rsv3; + opcode = copy.opcode; + masked = copy.masked; + mask = null; + if (copy.mask != null) + { + mask = new byte[copy.mask.length]; + System.arraycopy(copy.mask,0,mask,0,mask.length); + } + data = copy.data.slice(); + continuationIndex = copy.continuationIndex; + continuation = copy.continuation; + } + public void assertValid() { if (opcode.isControlFrame()) @@ -340,7 +370,7 @@ public class WebSocketFrame implements Frame data = ByteBuffer.allocate(len); BufferUtil.clearToFill(data); data.put(buf,0,len); - BufferUtil.flipToFill(data); + BufferUtil.flipToFlush(data,0); return this; } @@ -369,7 +399,7 @@ public class WebSocketFrame implements Frame data = ByteBuffer.allocate(len); BufferUtil.clearToFill(data); data.put(buf,0,len); - BufferUtil.flipToFill(data); + BufferUtil.flipToFlush(data,0); return this; } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java index a766306f6f7..aa78c172e77 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/GeneratorParserRoundtripTest.java @@ -42,7 +42,7 @@ public class GeneratorParserRoundtripTest Generator gen = new Generator(policy,bufferPool); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; @@ -81,7 +81,7 @@ public class GeneratorParserRoundtripTest Generator gen = new Generator(policy,bufferPool); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_1.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_1.java index e17a7442b9f..5a20abf89aa 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_1.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_1.java @@ -325,7 +325,7 @@ public class TestABCase1_1 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -359,7 +359,7 @@ public class TestABCase1_1 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -393,7 +393,7 @@ public class TestABCase1_1 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -427,7 +427,7 @@ public class TestABCase1_1 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -466,7 +466,7 @@ public class TestABCase1_1 policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -503,7 +503,7 @@ public class TestABCase1_1 policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -527,7 +527,7 @@ public class TestABCase1_1 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_2.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_2.java index 9ff5cedfc16..ce2cf252370 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_2.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase1_2.java @@ -340,7 +340,7 @@ public class TestABCase1_2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -374,7 +374,7 @@ public class TestABCase1_2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -408,7 +408,7 @@ public class TestABCase1_2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -442,7 +442,7 @@ public class TestABCase1_2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -477,7 +477,7 @@ public class TestABCase1_2 policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -514,7 +514,7 @@ public class TestABCase1_2 policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -538,7 +538,7 @@ public class TestABCase1_2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase2.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase2.java index a47844264a1..ad068f43394 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase2.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase2.java @@ -199,7 +199,7 @@ public class TestABCase2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -229,7 +229,7 @@ public class TestABCase2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -252,7 +252,7 @@ public class TestABCase2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -283,7 +283,7 @@ public class TestABCase2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -328,7 +328,7 @@ public class TestABCase2 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals("error should be returned for too large of ping payload",1,capture.getErrorCount(ProtocolException.class)); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase4.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase4.java index 5827e7f1fae..50984c7fcd5 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase4.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase4.java @@ -41,7 +41,7 @@ public class TestABCase4 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ; @@ -63,7 +63,7 @@ public class TestABCase4 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ; @@ -86,7 +86,7 @@ public class TestABCase4 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ; @@ -108,7 +108,7 @@ public class TestABCase4 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ; diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase7_3.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase7_3.java index 503d54d8fc0..caa36352045 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase7_3.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/TestABCase7_3.java @@ -71,7 +71,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -105,7 +105,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class)); @@ -146,7 +146,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -205,7 +205,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -276,7 +276,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); capture.assertNoErrors(); @@ -346,7 +346,7 @@ public class TestABCase7_3 Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(expected); Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class)); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriverTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriverTest.java index 965cabb62d7..8680f1ee1b3 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriverTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/driver/WebSocketEventDriverTest.java @@ -60,7 +60,7 @@ public class WebSocketEventDriverTest LocalWebSocketConnection conn = new LocalWebSocketConnection(testname); driver.setConnection(conn); driver.onConnect(); - driver.onFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); + driver.incoming(new CloseInfo(StatusCode.NORMAL).asFrame()); socket.capture.assertEventCount(2); socket.capture.assertEventStartsWith(0,"onWebSocketConnect"); @@ -76,8 +76,8 @@ public class WebSocketEventDriverTest LocalWebSocketConnection conn = new LocalWebSocketConnection(testname); driver.setConnection(conn); driver.onConnect(); - driver.onFrame(makeBinaryFrame("Hello World",true)); - driver.onFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); + driver.incoming(makeBinaryFrame("Hello World",true)); + driver.incoming(new CloseInfo(StatusCode.NORMAL).asFrame()); socket.capture.assertEventCount(3); socket.capture.assertEventStartsWith(0,"onConnect"); @@ -94,10 +94,10 @@ public class WebSocketEventDriverTest LocalWebSocketConnection conn = new LocalWebSocketConnection(testname); driver.setConnection(conn); driver.onConnect(); - driver.onFrame(new WebSocketFrame(OpCode.PING).setPayload("PING")); - driver.onFrame(WebSocketFrame.text("Text Me")); - driver.onFrame(WebSocketFrame.binary().setPayload("Hello Bin")); - driver.onFrame(new CloseInfo(StatusCode.SHUTDOWN).asFrame()); + driver.incoming(new WebSocketFrame(OpCode.PING).setPayload("PING")); + driver.incoming(WebSocketFrame.text("Text Me")); + driver.incoming(WebSocketFrame.binary().setPayload("Hello Bin")); + driver.incoming(new CloseInfo(StatusCode.SHUTDOWN).asFrame()); socket.capture.assertEventCount(6); socket.capture.assertEventStartsWith(0,"onConnect("); @@ -117,8 +117,8 @@ public class WebSocketEventDriverTest LocalWebSocketConnection conn = new LocalWebSocketConnection(testname); driver.setConnection(conn); driver.onConnect(); - driver.onFrame(makeBinaryFrame("Hello World",true)); - driver.onFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); + driver.incoming(makeBinaryFrame("Hello World",true)); + driver.incoming(new CloseInfo(StatusCode.NORMAL).asFrame()); socket.capture.assertEventCount(3); socket.capture.assertEventStartsWith(0,"onConnect"); @@ -135,8 +135,8 @@ public class WebSocketEventDriverTest LocalWebSocketConnection conn = new LocalWebSocketConnection(testname); driver.setConnection(conn); driver.onConnect(); - driver.onFrame(WebSocketFrame.text("Hello World")); - driver.onFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); + driver.incoming(WebSocketFrame.text("Hello World")); + driver.incoming(new CloseInfo(StatusCode.NORMAL).asFrame()); socket.capture.assertEventCount(3); socket.capture.assertEventStartsWith(0,"onWebSocketConnect"); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ClosePayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ClosePayloadParserTest.java index 33f02ed6e32..4098033ee3d 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ClosePayloadParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ClosePayloadParserTest.java @@ -52,7 +52,7 @@ public class ClosePayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/FrameParseCapture.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/FrameParseCapture.java index dc54a2af63d..d9e88b2e103 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/FrameParseCapture.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/FrameParseCapture.java @@ -23,12 +23,10 @@ import java.util.List; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.protocol.OpCode; -import org.eclipse.jetty.websocket.protocol.Parser; -import org.eclipse.jetty.websocket.protocol.WebSocketFrame; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.junit.Assert; -public class FrameParseCapture implements Parser.Listener +public class FrameParseCapture implements IncomingFrames { private static final Logger LOG = Log.getLogger(FrameParseCapture.class); private List frames = new ArrayList<>(); @@ -94,15 +92,15 @@ public class FrameParseCapture implements Parser.Listener } @Override - public void onFrame(WebSocketFrame frame) - { - frames.add(frame); - } - - @Override - public void onWebSocketException(WebSocketException e) + public void incoming(WebSocketException e) { LOG.warn(e); errors.add(e); } + + @Override + public void incoming(WebSocketFrame frame) + { + frames.add(frame); + } } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java index 0578db75f9e..fc5d13a1d49 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/ParserTest.java @@ -37,7 +37,7 @@ public class ParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/PingPayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/PingPayloadParserTest.java index 927b3308131..c2cd6d5cb0c 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/PingPayloadParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/PingPayloadParserTest.java @@ -42,7 +42,7 @@ public class PingPayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/RFC6455ExamplesParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/RFC6455ExamplesParserTest.java index 12a865200cc..255226c1fad 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/RFC6455ExamplesParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/RFC6455ExamplesParserTest.java @@ -38,7 +38,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); ByteBuffer buf = ByteBuffer.allocate(16); @@ -82,7 +82,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -105,7 +105,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -135,7 +135,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -175,7 +175,7 @@ public class RFC6455ExamplesParserTest policy.setBufferSize(80000); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -206,7 +206,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -229,7 +229,7 @@ public class RFC6455ExamplesParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/TextPayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/TextPayloadParserTest.java index 4748225e7eb..96cb08f1ab0 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/TextPayloadParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/protocol/TextPayloadParserTest.java @@ -55,7 +55,7 @@ public class TextPayloadParserTest Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertHasErrors(MessageTooLargeException.class,1); @@ -93,7 +93,7 @@ public class TextPayloadParserTest policy.setMaxPayloadSize(100000); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -128,7 +128,7 @@ public class TextPayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -165,7 +165,7 @@ public class TextPayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -192,7 +192,7 @@ public class TextPayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); @@ -218,7 +218,7 @@ public class TextPayloadParserTest WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); - parser.setListener(capture); + parser.setIncomingFramesHandler(capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java index 0ab6ca21caf..2388dcb5dab 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java @@ -16,9 +16,6 @@ package org.eclipse.jetty.websocket.server; import java.io.IOException; -import java.util.List; - -import org.eclipse.jetty.websocket.api.Extension; public interface WebSocketHandshake { @@ -27,8 +24,7 @@ public interface WebSocketHandshake * * @param request * @param response - * @param extensions * @param acceptedSubProtocol */ - public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response, List extensions) throws IOException; + public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response) throws IOException; } \ No newline at end of file diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index e34ce488451..97bcd88c1a5 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -47,12 +47,9 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.driver.EventMethodsCache; import org.eclipse.jetty.websocket.driver.WebSocketEventDriver; import org.eclipse.jetty.websocket.extensions.WebSocketExtensionRegistry; -import org.eclipse.jetty.websocket.extensions.deflate.DeflateFrameExtension; -import org.eclipse.jetty.websocket.extensions.fragment.FragmentExtension; -import org.eclipse.jetty.websocket.extensions.identity.IdentityExtension; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.eclipse.jetty.websocket.io.WebSocketAsyncConnection; import org.eclipse.jetty.websocket.protocol.ExtensionConfig; -import org.eclipse.jetty.websocket.protocol.Parser; import org.eclipse.jetty.websocket.server.handshake.HandshakeHixie76; import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455; @@ -64,14 +61,6 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class); private final Queue connections = new ConcurrentLinkedQueue(); - // TODO: replace with ExtensionRegistry in websocket-core - private final Map> extensionClasses = new HashMap<>(); - { - extensionClasses.put("identity",IdentityExtension.class); - extensionClasses.put("fragment",FragmentExtension.class); - extensionClasses.put("x-deflate-frame",DeflateFrameExtension.class); - } - private final Map handshakes = new HashMap<>(); { handshakes.put(HandshakeRFC6455.VERSION,new HandshakeRFC6455()); @@ -86,7 +75,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock private final WebSocketPolicy basePolicy; private final EventMethodsCache methodsCache; private final ByteBufferPool bufferPool; - private final ExtensionRegistry extensionRegistry; + private final WebSocketExtensionRegistry extensionRegistry; private WebSocketCreator creator; private Class firstRegisteredClass; @@ -100,7 +89,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock this.basePolicy = policy; this.methodsCache = new EventMethodsCache(); this.bufferPool = bufferPool; - this.extensionRegistry = new WebSocketExtensionRegistry(); + this.extensionRegistry = new WebSocketExtensionRegistry(basePolicy,bufferPool); this.creator = this; // Create supportedVersions @@ -194,12 +183,9 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock return this.creator; } - /** - * @return A modifiable map of extension name to extension class - */ - public Map> getExtensionClassesMap() + public ExtensionRegistry getExtensionRegistry() { - return extensionClasses; + return extensionRegistry; } /** @@ -296,6 +282,12 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock this.creator = creator; } + private IncomingFrames setupExtensionChain(WebSocketEventDriver websocket, List extensions) + { + // TODO Auto-generated method stub + return websocket; + } + /** * Upgrade the request/response to a WebSocket Connection. *

@@ -354,19 +346,12 @@ public class WebSocketServerFactory extends AbstractLifeCycle implements WebSock // Initialize / Negotiate Extensions List extensions = initExtensions(request.getExtensions()); - // TODO : bind extensions? layer extensions? how? - // TODO : wrap websocket with extension processing Parser.Listener list - - Parser.ListenerList listenerList = new Parser.ListenerList(); - listenerList.addListener(websocket); - - connection.getParser().setListener(listenerList); - // TODO : connection.setWriteExtensions(extensions); - // TODO : implement endpoint.write() layer for outgoing extension frames. + IncomingFrames incoming = setupExtensionChain(websocket,extensions); + connection.getParser().setIncomingFramesHandler(incoming); // Process (version specific) handshake response LOG.debug("Handshake Response: {}",handshaker); - handshaker.doHandshakeResponse(request,response,extensions); + handshaker.doHandshakeResponse(request,response); // Add connection addConnection(connection); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeHixie76.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeHixie76.java index 0b2d6d1b6b1..38aac0aaae5 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeHixie76.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeHixie76.java @@ -16,9 +16,7 @@ package org.eclipse.jetty.websocket.server.handshake; import java.io.IOException; -import java.util.List; -import org.eclipse.jetty.websocket.api.Extension; import org.eclipse.jetty.websocket.server.ServletWebSocketRequest; import org.eclipse.jetty.websocket.server.ServletWebSocketResponse; import org.eclipse.jetty.websocket.server.WebSocketHandshake; @@ -34,7 +32,7 @@ public class HandshakeHixie76 implements WebSocketHandshake public static final int VERSION = 0; @Override - public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response, List extensions) throws IOException + public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response) throws IOException { // TODO: implement the Hixie76 handshake? throw new IOException("Not implemented yet"); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeRFC6455.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeRFC6455.java index fea99354af1..61ac18546d8 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeRFC6455.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/handshake/HandshakeRFC6455.java @@ -16,12 +16,11 @@ package org.eclipse.jetty.websocket.server.handshake; import java.io.IOException; -import java.util.List; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.websocket.api.Extension; import org.eclipse.jetty.websocket.protocol.AcceptHash; +import org.eclipse.jetty.websocket.protocol.ExtensionConfig; import org.eclipse.jetty.websocket.server.ServletWebSocketRequest; import org.eclipse.jetty.websocket.server.ServletWebSocketResponse; import org.eclipse.jetty.websocket.server.WebSocketHandshake; @@ -35,7 +34,7 @@ public class HandshakeRFC6455 implements WebSocketHandshake public static final int VERSION = 13; @Override - public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response, List extensions) throws IOException + public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response) throws IOException { String key = request.getHeader("Sec-WebSocket-Key"); @@ -54,11 +53,11 @@ public class HandshakeRFC6455 implements WebSocketHandshake response.addHeader("Sec-WebSocket-Protocol",response.getAcceptedSubProtocol()); } - if (extensions != null) + if (request.getExtensions() != null) { - for (Extension ext : extensions) + for (ExtensionConfig ext : request.getExtensions()) { - response.addHeader("Sec-WebSocket-Extensions",ext.getConfig().getParameterizedName()); + response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName()); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java index 2e337340bcc..fa54d36f490 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java @@ -53,6 +53,7 @@ public class IdentityExtensionTest client.addExtensions("identity;param=0"); client.addExtensions("identity;param=1, identity ; param = '2' ; other = ' some = value '"); client.setProtocols("onConnect"); + client.setDebug(true); try { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java index b1cf6527ffc..789ab727c26 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java @@ -40,6 +40,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.eclipse.jetty.websocket.protocol.Generator; import org.eclipse.jetty.websocket.protocol.Parser; import org.eclipse.jetty.websocket.protocol.WebSocketFrame; @@ -61,7 +62,7 @@ public class WebSocketLoadRFC6455Test private/* final */AsyncEndPoint _endp; private final Generator _generator; private final Parser _parser; - private final Parser.Listener _handler = new Parser.Listener() + private final IncomingFrames _handler = new IncomingFrames() { /* * public void close(int code,String message) { } @@ -70,16 +71,15 @@ public class WebSocketLoadRFC6455Test */ @Override - public void onFrame(WebSocketFrame frame) + public void incoming(WebSocketException e) { // TODO Auto-generated method stub } @Override - public void onWebSocketException(WebSocketException e) + public void incoming(WebSocketFrame frame) { // TODO Auto-generated method stub - } }; private volatile ByteBuffer _response; diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java index 45eec6d370e..a134f70a8bf 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java @@ -49,6 +49,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.eclipse.jetty.websocket.protocol.CloseInfo; import org.eclipse.jetty.websocket.protocol.Generator; import org.eclipse.jetty.websocket.protocol.OpCode; @@ -65,11 +66,11 @@ import org.junit.Assert; * This client is NOT intended to be performant or follow the websocket spec religiously. In fact, being able to deviate from the websocket spec at will * is desired for this client to operate properly for the unit testing within this module. */ -public class BlockheadClient implements Parser.Listener +public class BlockheadClient implements IncomingFrames { private static final Logger LOG = Log.getLogger(BlockheadClient.class); /** Set to true to disable timeouts (for debugging reasons) */ - private static final boolean DEBUG = false; + private boolean debug = false; private final URI destHttpURI; private final URI destWebsocketURI; private final ByteBufferPool bufferPool; @@ -103,7 +104,7 @@ public class BlockheadClient implements Parser.Listener bufferPool = new StandardByteBufferPool(policy.getBufferSize()); generator = new UnitGenerator(); parser = new Parser(policy); - parser.setListener(this); + parser.setIncomingFramesHandler(this); incomingFrameQueue = new LinkedBlockingDeque<>(); } @@ -198,6 +199,22 @@ public class BlockheadClient implements Parser.Listener return destWebsocketURI; } + @Override + public void incoming(WebSocketException e) + { + LOG.warn(e); + } + + @Override + public void incoming(WebSocketFrame frame) + { + LOG.debug("incoming({})",frame); + if (!incomingFrameQueue.offerLast(frame)) + { + throw new RuntimeException("Unable to queue incoming frame: " + frame); + } + } + public void lookFor(String string) throws IOException { String orig = string; @@ -227,22 +244,6 @@ public class BlockheadClient implements Parser.Listener } } - @Override - public void onFrame(WebSocketFrame frame) - { - LOG.debug("onFrame({})",frame); - if (!incomingFrameQueue.offerLast(frame)) - { - throw new RuntimeException("Unable to queue incoming frame: " + frame); - } - } - - @Override - public void onWebSocketException(WebSocketException e) - { - LOG.warn(e); - } - public int read(ByteBuffer buf) throws IOException { int len = 0; @@ -285,7 +286,7 @@ public class BlockheadClient implements Parser.Listener { /* ignore */ } - if (!DEBUG && (System.currentTimeMillis() > expireOn)) + if (!debug && (System.currentTimeMillis() > expireOn)) { throw new TimeoutException("Timeout reading all of the desired frames"); } @@ -348,6 +349,11 @@ public class BlockheadClient implements Parser.Listener writeRaw(req.toString()); } + public void setDebug(boolean flag) + { + this.debug = flag; + } + public void setProtocols(String protocols) { this.protocols = protocols; diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/FrameParseCapture.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/FrameParseCapture.java index bd14faac781..7a5715536fe 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/FrameParseCapture.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/FrameParseCapture.java @@ -23,11 +23,11 @@ import java.util.List; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.protocol.Parser; +import org.eclipse.jetty.websocket.io.IncomingFrames; import org.eclipse.jetty.websocket.protocol.WebSocketFrame; import org.junit.Assert; -public class FrameParseCapture implements Parser.Listener +public class FrameParseCapture implements IncomingFrames { private static final Logger LOG = Log.getLogger(FrameParseCapture.class); private List frames = new ArrayList<>(); @@ -95,15 +95,15 @@ public class FrameParseCapture implements Parser.Listener } @Override - public void onFrame(WebSocketFrame frame) - { - frames.add(frame); - } - - @Override - public void onWebSocketException(WebSocketException e) + public void incoming(WebSocketException e) { LOG.warn(e); errors.add(e); } + + @Override + public void incoming(WebSocketFrame frame) + { + frames.add(frame); + } } From fc658c3805edb912729005927a52a6a44dc6d862 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 12 Jul 2012 11:29:40 -0700 Subject: [PATCH 2/2] Fixing NPE --- .../jetty/websocket/protocol/Parser.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java index 2ed4f647140..3fce2431fea 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/protocol/Parser.java @@ -456,15 +456,22 @@ public class Parser public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("Parser ["); - builder.append(incomingFramesHandler.getClass().getSimpleName()); - builder.append(", state="); + builder.append("Parser["); + if (incomingFramesHandler == null) + { + builder.append("NO_HANDLER"); + } + else + { + builder.append(incomingFramesHandler.getClass().getSimpleName()); + } + builder.append(",s="); builder.append(state); - builder.append(", cursor="); + builder.append(",c="); builder.append(cursor); - builder.append(", payloadLength="); + builder.append(",len="); builder.append(payloadLength); - builder.append(", frame="); + builder.append(",f="); builder.append(frame); builder.append("]"); return builder.toString();