diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java index cee126d2534..6ac2a5147fb 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java @@ -237,6 +237,18 @@ public class UpgradeRequest implements HandshakeRequest this.cookies = cookies; } + public void setHeader(String name, List values) + { + headers.put(name,values); + } + + public void setHeader(String name, String value) + { + List values = new ArrayList<>(); + values.add(value); + setHeader(name,values); + } + public void setHttpVersion(String httpVersion) { this.httpVersion = httpVersion; diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java index 823ab442b06..3195b4631fe 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java @@ -39,7 +39,7 @@ public interface WebSocketConnection * @see StatusCode * @see #close(int, String) */ - public void close(); + public void close() throws IOException; /** * Send a websocket Close frame, with status code. @@ -52,7 +52,7 @@ public interface WebSocketConnection * the (optional) reason. (can be null for no reason) * @see StatusCode */ - public void close(int statusCode, String reason); + public void close(int statusCode, String reason) throws IOException; /** * Get the address of the local side. @@ -102,8 +102,11 @@ public interface WebSocketConnection * NIO style with callbacks, allows for knowledge of successful ping send. *

* Use @OnWebSocketFrame and monitor Pong frames + * + * @param the + * ping application data */ - Future ping(byte payload[]) throws IOException; + void ping(ByteBuffer buf) throws IOException; /** * Suspend a the incoming read events on the connection. diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java index 68de551830c..7d2e62f248b 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java @@ -26,9 +26,12 @@ public interface WebSocketListener /** * A WebSocket binary frame has been received. * - * @param payload the raw payload array received - * @param offset the offset in the payload array where the data starts - * @param len the length of bytes in the payload + * @param payload + * the raw payload array received + * @param offset + * the offset in the payload array where the data starts + * @param len + * the length of bytes in the payload */ void onWebSocketBinary(byte payload[], int offset, int len); diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Extension.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Extension.java index 512cfafe869..7671d1d9845 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Extension.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Extension.java @@ -25,28 +25,8 @@ import javax.net.websocket.extensions.FrameHandler; *

* That work is performed by the two {@link FrameHandler} implementations for incoming and outgoing frame handling. */ -public interface Extension extends javax.net.websocket.extensions.Extension +public interface Extension extends IncomingFrames, OutgoingFrames { - /** - * Create an instance of a Incoming {@link FrameHandler} for working with frames destined for the End User WebSocket Object. - * - * @param the - * incoming {@link FrameHandler} to wrap - * @return the frame handler for incoming frames. - */ - @Override - public FrameHandler createIncomingFrameHandler(FrameHandler incoming); - - /** - * Create an instance of a Outgoing {@link FrameHandler} for working with frames destined for the Network Bytes Layer. - * - * @param the - * outgoing {@link FrameHandler} to wrap - * @return the frame handler for outgoing frames. - */ - @Override - public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing); - /** * The active configuration for this extension. * @@ -59,7 +39,6 @@ public interface Extension extends javax.net.websocket.extensions.Extension *

* Also known as the extension-token per Section 9.1. Negotiating Extensions. */ - @Override public String getName(); /** @@ -101,4 +80,20 @@ public interface Extension extends javax.net.websocket.extensions.Extension * now free to validate the conformance to spec of TEXT Data Frames. */ public abstract boolean isTextDataDecoder(); + + /** + * Set the next {@link IncomingFrames} to call in the chain. + * + * @param nextIncoming + * the next incoming extension + */ + public void setNextIncomingFrames(IncomingFrames nextIncoming); + + /** + * Set the next {@link OutgoingFrames} to call in the chain. + * + * @param nextOutgoing + * the next outgoing extension + */ + public void setNextOutgoingFrames(OutgoingFrames nextOutgoing); } \ No newline at end of file diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/ExtensionFactory.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/ExtensionFactory.java index 4114f5f7baa..c35fc4ba5e8 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/ExtensionFactory.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/ExtensionFactory.java @@ -24,26 +24,26 @@ import java.util.Map; import java.util.ServiceLoader; import java.util.Set; -public class ExtensionFactory implements Iterable +public abstract class ExtensionFactory implements Iterable> { private ServiceLoader extensionLoader = ServiceLoader.load(Extension.class); - private Map availableExtensions; + private Map> availableExtensions; public ExtensionFactory() { availableExtensions = new HashMap<>(); for (Extension ext : extensionLoader) { - availableExtensions.put(ext.getName(),ext); + availableExtensions.put(ext.getName(),ext.getClass()); } } - public Map getAvailableExtensions() + public Map> getAvailableExtensions() { return availableExtensions; } - public Extension getExtension(String name) + public Class getExtension(String name) { return availableExtensions.get(name); } @@ -59,12 +59,14 @@ public class ExtensionFactory implements Iterable } @Override - public Iterator iterator() + public Iterator> iterator() { return availableExtensions.values().iterator(); } - public void register(String name, Extension extension) + public abstract Extension newInstance(ExtensionConfig config); + + public void register(String name, Class extension) { availableExtensions.put(name,extension); } diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Frame.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Frame.java index 4691ca20117..944636171c4 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Frame.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/Frame.java @@ -27,6 +27,7 @@ public interface Frame extends javax.net.websocket.extensions.Frame { public static enum Type { + CONTINUATION((byte)0x00), TEXT((byte)0x01), BINARY((byte)0x02), CLOSE((byte)0x08), @@ -35,12 +36,6 @@ public interface Frame extends javax.net.websocket.extensions.Frame public static Type from(byte op) { - if (op == 0) - { - // continuation has no type, but is a valid opcode. - return null; - } - for (Type type : values()) { if (type.opcode == op) @@ -82,12 +77,18 @@ public interface Frame extends javax.net.websocket.extensions.Frame public byte[] getMask(); + public byte getOpCode(); + public ByteBuffer getPayload(); public int getPayloadLength(); + public int getPayloadStart(); + public Type getType(); + public boolean hasPayload(); + public boolean isContinuation(); public boolean isFin(); @@ -106,4 +107,10 @@ public interface Frame extends javax.net.websocket.extensions.Frame public boolean isRsv2(); public boolean isRsv3(); + + public void notifySendFailed(Throwable t); + + public void notifySendSuccess(); + + public int remaining(); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IncomingFrames.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java similarity index 86% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IncomingFrames.java rename to jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java index 73cedd185a1..dea867e1fc3 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IncomingFrames.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java @@ -16,10 +16,9 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.io; +package org.eclipse.jetty.websocket.api.extensions; import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.common.WebSocketFrame; /** * Interface for dealing with Incoming Frames. @@ -28,5 +27,5 @@ public interface IncomingFrames { public void incomingError(WebSocketException e); - public void incomingFrame(WebSocketFrame frame); + public void incomingFrame(Frame frame); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/OutgoingFrames.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java similarity index 84% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/OutgoingFrames.java rename to jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java index 0bbc71c434f..f119d7d8aa1 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/OutgoingFrames.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java @@ -16,19 +16,17 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.io; +package org.eclipse.jetty.websocket.api.extensions; import java.io.IOException; import java.util.concurrent.Future; import javax.net.websocket.SendResult; -import org.eclipse.jetty.websocket.common.WebSocketFrame; - /** * Interface for dealing with frames outgoing to the network (eventually) */ public interface OutgoingFrames { - Future outgoingFrame(WebSocketFrame frame) throws IOException; + Future outgoingFrame(Frame frame) throws IOException; } diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/JettyClientContainer.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/JettyClientContainer.java new file mode 100644 index 00000000000..6ce0ab47fd4 --- /dev/null +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/JettyClientContainer.java @@ -0,0 +1,93 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.client; + +import java.util.Set; + +import javax.net.websocket.ClientContainer; +import javax.net.websocket.ClientEndpointConfiguration; +import javax.net.websocket.DeploymentException; +import javax.net.websocket.Endpoint; +import javax.net.websocket.Session; + +public class JettyClientContainer implements ClientContainer +{ + @Override + public void connectToServer(Endpoint endpoint, ClientEndpointConfiguration olc) throws DeploymentException + { + // TODO Auto-generated method stub + + } + + @Override + public Set getActiveSessions() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getInstalledExtensions() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getMaxBinaryMessageBufferSize() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getMaxSessionIdleTimeout() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getMaxTextMessageBufferSize() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setMaxBinaryMessageBufferSize(long max) + { + // TODO Auto-generated method stub + + } + + @Override + public void setMaxSessionIdleTimeout(long timeout) + { + // TODO Auto-generated method stub + + } + + @Override + public void setMaxTextMessageBufferSize(long max) + { + // TODO Auto-generated method stub + + } +} diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClientFactory.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClientFactory.java index 4a8591f46c5..3fb34d9b7d6 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClientFactory.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClientFactory.java @@ -40,10 +40,10 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.client.internal.ConnectionManager; import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriverFactory; -import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; +import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; public class WebSocketClientFactory extends ContainerLifeCycle { @@ -54,7 +54,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle private final Scheduler scheduler; private final EventDriverFactory eventDriverFactory; private final WebSocketPolicy policy; - private final WebSocketExtensionRegistry extensionRegistry; + private final WebSocketExtensionFactory extensionRegistry; private SocketAddress bindAddress; private final Queue sessions = new ConcurrentLinkedQueue<>(); @@ -98,7 +98,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle } this.policy = WebSocketPolicy.newClientPolicy(); - this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool); + this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool); this.connectionManager = new ConnectionManager(bufferPool,executor,scheduler,sslContextFactory,policy); addBean(this.connectionManager); @@ -205,7 +205,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle LOG.debug("Session Opened: {}",session); } boolean ret = sessions.offer(session); - session.onConnect(); + session.open(); return ret; } diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/ConnectionManager.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/ConnectionManager.java index c964f45fa16..357ab9ee1ae 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/ConnectionManager.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/ConnectionManager.java @@ -95,13 +95,20 @@ public class ConnectionManager extends ContainerLifeCycle clients.add(client); } - private void closeConnections() + private void closeAllConnections() { for (DefaultWebSocketClient client : clients) { if (client.getConnection() != null) { - client.getConnection().close(); + try + { + client.getConnection().close(); + } + catch (IOException e) + { + LOG.debug("During Close All Connections",e); + } } } } @@ -138,7 +145,7 @@ public class ConnectionManager extends ContainerLifeCycle @Override protected void doStop() throws Exception { - closeConnections(); + closeAllConnections(); clients.clear(); super.doStop(); } diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/UpgradeConnection.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/UpgradeConnection.java index 3ca371912f6..2aa6b9395bd 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/UpgradeConnection.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/UpgradeConnection.java @@ -38,14 +38,13 @@ import org.eclipse.jetty.websocket.api.UpgradeException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.ClientUpgradeResponse; import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; import org.eclipse.jetty.websocket.common.AcceptHash; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; /** * This is the initial connection handling that exists immediately after physical connection is established to destination server. @@ -217,13 +216,17 @@ public class UpgradeConnection extends AbstractConnection EventDriver websocket = client.getWebSocket(); WebSocketPolicy policy = client.getPolicy(); String acceptedSubProtocol = response.getAcceptedSubProtocol(); - WebSocketSession session = new WebSocketSession(websocket,connection,policy,acceptedSubProtocol); + + WebSocketSession session = new WebSocketSession(request.getRequestURI(),websocket,connection); + session.setPolicy(policy); + session.setNegotiatedSubprotocol(acceptedSubProtocol); + connection.setSession(session); List extensions = client.getFactory().initExtensions(response.getExtensions()); // Start with default routing. IncomingFrames incoming = session; - OutgoingFrames outgoing = connection; + // OutgoingFrames outgoing = connection; // Connect extensions if (extensions != null) @@ -254,7 +257,7 @@ public class UpgradeConnection extends AbstractConnection } // configure session for outgoing flows - session.setOutgoing(outgoing); + // session.setOutgoing(outgoing); // configure connection for incoming flows connection.getParser().setIncomingFramesHandler(incoming); diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/WebSocketClientConnection.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/WebSocketClientConnection.java index 1fe36d7c2d6..1cd23dd8777 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/WebSocketClientConnection.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/io/WebSocketClientConnection.java @@ -19,20 +19,20 @@ package org.eclipse.jetty.websocket.client.internal.io; import java.io.IOException; -import java.util.List; +import java.net.InetSocketAddress; import java.util.concurrent.Executor; import java.util.concurrent.Future; import javax.net.websocket.SendResult; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.client.WebSocketClientFactory; import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; /** * Client side WebSocket physical connection. @@ -53,17 +53,23 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection this.masker = client.getMasker(); } - @Override - public void configureFromExtensions(List extensions) - { - /* do nothing */ - } - public DefaultWebSocketClient getClient() { return client; } + @Override + public InetSocketAddress getLocalAddress() + { + return getEndPoint().getLocalAddress(); + } + + @Override + public InetSocketAddress getRemoteAddress() + { + return getEndPoint().getRemoteAddress(); + } + @Override public void onClose() { @@ -83,14 +89,17 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { - masker.setMask(frame); + if (frame instanceof WebSocketFrame) + { + masker.setMask((WebSocketFrame)frame); + } return super.outgoingFrame(frame); } @Override - public void setIncoming(IncomingFrames incoming) + public void setNextIncomingFrames(IncomingFrames incoming) { getParser().setIncomingFramesHandler(incoming); } diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/mux/MuxClientAddHandler.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/mux/MuxClientAddHandler.java index 2c2c6e7b96d..52fd29588c1 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/mux/MuxClientAddHandler.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/internal/mux/MuxClientAddHandler.java @@ -18,9 +18,9 @@ package org.eclipse.jetty.websocket.client.internal.mux; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; public class MuxClientAddHandler implements MuxAddClient { diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/BlockheadServer.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/BlockheadServer.java index 1a0b7e25fd5..2ec617e7fa6 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/BlockheadServer.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/BlockheadServer.java @@ -53,15 +53,16 @@ import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.AcceptHash; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; import org.junit.Assert; /** @@ -81,7 +82,7 @@ public class BlockheadServer private final Parser parser; private final Generator generator; private final AtomicInteger parseCount; - private final WebSocketExtensionRegistry extensionRegistry; + private final WebSocketExtensionFactory extensionRegistry; /** Set to true to disable timeouts (for debugging reasons) */ private boolean debug = false; @@ -100,7 +101,7 @@ public class BlockheadServer this.parser = new Parser(policy); this.parseCount = new AtomicInteger(0); this.generator = new Generator(policy,bufferPool,false); - this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool); + this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool); } public void close() throws IOException @@ -141,7 +142,7 @@ public class BlockheadServer LOG.debug("Echo Frames [expecting {}]",expectedFrames); IncomingFramesCapture cap = readFrames(expectedFrames,timeoutUnit,timeoutDuration); // now echo them back. - for (WebSocketFrame frame : cap.getFrames()) + for (Frame frame : cap.getFrames()) { write(frame); } @@ -197,7 +198,7 @@ public class BlockheadServer } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { LOG.debug("incoming({})",frame); int count = parseCount.incrementAndGet(); @@ -210,7 +211,7 @@ public class BlockheadServer } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { ByteBuffer buf = generator.generate(frame); if (LOG.isDebugEnabled()) @@ -220,7 +221,7 @@ public class BlockheadServer BufferUtil.writeTo(buf,out); out.flush(); - if (frame.getOpCode() == OpCode.CLOSE) + if (frame.getType().getOpCode() == OpCode.CLOSE) { disconnect(); } @@ -434,16 +435,16 @@ public class BlockheadServer getOutputStream().write(buf,offset,length); } - public void write(int b) throws IOException - { - getOutputStream().write(b); - } - - public void write(WebSocketFrame frame) throws IOException + public void write(Frame frame) throws IOException { LOG.debug("write(Frame->{}) to {}",frame,outgoing); outgoing.outgoingFrame(frame); } + + public void write(int b) throws IOException + { + getOutputStream().write(b); + } } private static final Logger LOG = Log.getLogger(BlockheadServer.class); diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/IncomingFramesCapture.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/IncomingFramesCapture.java index 09f662d47c7..7ee463007cf 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/IncomingFramesCapture.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/blockhead/IncomingFramesCapture.java @@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; import org.junit.Assert; public class IncomingFramesCapture implements IncomingFrames @@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames System.err.printf("Captured %d incoming frames%n",frames.size()); for (int i = 0; i < frames.size(); i++) { - WebSocketFrame frame = frames.get(i); + Frame frame = frames.get(i); System.err.printf("[%3d] %s%n",i,frame); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); } @@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { WebSocketFrame copy = new WebSocketFrame(frame); frames.add(copy); diff --git a/jetty-websocket/websocket-common/pom.xml b/jetty-websocket/websocket-common/pom.xml index d59762a8abe..afc4d345c88 100644 --- a/jetty-websocket/websocket-common/pom.xml +++ b/jetty-websocket/websocket-common/pom.xml @@ -20,7 +20,6 @@ org.eclipse.jetty.drafts javax.net.websocket-api 0.006.0.EDR-SNAPSHOT - provided org.eclipse.jetty.websocket diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FailedFuture.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FailedFuture.java new file mode 100644 index 00000000000..e1df5ca9b69 --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/FailedFuture.java @@ -0,0 +1,58 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; + +import javax.net.websocket.SendHandler; +import javax.net.websocket.SendResult; + +public class FailedFuture extends FutureTask implements Future +{ + private static class FailedRunner implements Callable + { + private SendHandler completion; + private Throwable error; + + public FailedRunner(SendHandler completion, Throwable error) + { + this.completion = completion; + this.error = error; + } + + @Override + public SendResult call() throws Exception + { + SendResult result = new SendResult(this.error); + if (completion != null) + { + completion.setResult(result); + } + return result; + } + } + + public FailedFuture(SendHandler completion, Throwable error) + { + super(new FailedRunner(completion,error)); + run(); + } +} 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 3112468b7b4..cb4e70651e5 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 @@ -29,6 +29,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * Generating a frame in WebSocket land. @@ -103,7 +104,7 @@ public class Generator this.validating = validating; } - public void assertFrameValid(WebSocketFrame frame) + public void assertFrameValid(Frame frame) { if (!validating) { @@ -131,7 +132,7 @@ public class Generator throw new ProtocolException("RSV3 not allowed to be set"); } - if (frame.isControlFrame()) + if (frame.getType().isControl()) { /* * RFC 6455 Section 5.5 @@ -153,7 +154,7 @@ public class Generator * * close frame payload is specially formatted which is checked in CloseInfo */ - if (frame.getOpCode() == OpCode.CLOSE) + if (frame.getType().getOpCode() == OpCode.CLOSE) { ByteBuffer payload = frame.getPayload(); @@ -191,11 +192,25 @@ public class Generator } } + /** + * generate a byte buffer based on the frame being passed in + * + * bufferSize is determined by the length of the payload + 28 for frame overhead + * + * @param frame + * @return + */ + public ByteBuffer generate(Frame frame) + { + int bufferSize = frame.getPayloadLength() + OVERHEAD; + return generate(bufferSize,frame); + } + /** * Generate, into a ByteBuffer, no more than bufferSize of contents from the frame. If the frame exceeds the bufferSize, then multiple calls to * {@link #generate(int, WebSocketFrame)} are required to obtain each window of ByteBuffer to complete the frame. */ - public ByteBuffer generate(int windowSize, WebSocketFrame frame) + public ByteBuffer generate(int windowSize, Frame frame) { if (windowSize < OVERHEAD) { @@ -204,22 +219,7 @@ public class Generator if (LOG.isDebugEnabled()) { - StringBuilder dbg = new StringBuilder(); - dbg.append(behavior); - dbg.append(" Generate.Frame["); - dbg.append("opcode=").append(frame.getOpCode()); - dbg.append(",fin=").append(frame.isFin()); - dbg.append(",cont=").append(frame.isContinuation()); - dbg.append(",rsv1=").append(frame.isRsv1()); - dbg.append(",rsv2=").append(frame.isRsv2()); - dbg.append(",rsv3=").append(frame.isRsv3()); - dbg.append(",mask=").append(frame.isMasked()); - dbg.append(",payloadLength=").append(frame.getPayloadLength()); - dbg.append(",payloadStart=").append(frame.getPayloadStart()); - dbg.append(",remaining=").append(frame.remaining()); - dbg.append(",position=").append(frame.position()); - dbg.append(']'); - LOG.debug(dbg.toString()); + LOG.debug("{} Generate: {}",behavior,frame); } /* @@ -260,6 +260,7 @@ public class Generator b |= 0x10; } + // NOTE: using .getOpCode() here, not .getType().getOpCode() for testing reasons byte opcode = frame.getOpCode(); if (frame.isContinuation()) @@ -366,20 +367,6 @@ public class Generator return buffer; } - /** - * generate a byte buffer based on the frame being passed in - * - * bufferSize is determined by the length of the payload + 28 for frame overhead - * - * @param frame - * @return - */ - public ByteBuffer generate(WebSocketFrame frame) - { - int bufferSize = frame.getPayloadLength() + OVERHEAD; - return generate(bufferSize,frame); - } - public boolean isRsv1InUse() { return rsv1InUse; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java index 731aa448ed4..384013f3883 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java @@ -18,14 +18,33 @@ package org.eclipse.jetty.websocket.common; +import java.io.IOException; import java.net.InetSocketAddress; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.SuspendToken; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; -public interface LogicalConnection extends OutgoingFrames +public interface LogicalConnection extends OutgoingFrames, SuspendToken { + /** + * Perform a quick check that the connection input is open. + * + * @throws IOException + * if the connection input is closed + */ + void assertInputOpen() throws IOException; + + /** + * Perform a quick check that the connection output is open. + * + * @throws IOException + * if the connection output is closed + */ + void assertOutputOpen() throws IOException; + /** * Send a websocket Close frame, without a status code or reason. *

@@ -55,12 +74,36 @@ public interface LogicalConnection extends OutgoingFrames void disconnect(); /** - * Get the remote Address in use for this connection. + * Get the local {@link InetSocketAddress} in use for this connection. + *

+ * Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost. * - * @return the remote address if available. (situations like mux extension and proxying makes this information unreliable) + * @return the local address. + */ + InetSocketAddress getLocalAddress(); + + /** + * The policy that the connection is running under. + * @return the policy for the connection + */ + WebSocketPolicy getPolicy(); + + /** + * Get the remote Address in use for this connection. + *

+ * Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost. + * + * @return the remote address. */ InetSocketAddress getRemoteAddress(); + /** + * Get the Session for this connection + * + * @return the Session for this connection + */ + WebSocketSession getSession(); + /** * Get the WebSocket connection State. * @@ -106,6 +149,24 @@ public interface LogicalConnection extends OutgoingFrames */ void onCloseHandshake(boolean incoming, CloseInfo close); + /** + * Set where the connection should send the incoming frames to. + *

+ * Often this is from the Parser to the start of the extension stack, and eventually on to the session. + * + * @param incoming + * the incoming frames handler + */ + void setNextIncomingFrames(IncomingFrames incoming); + + /** + * Set the session associated with this connection + * + * @param session + * the session + */ + void setSession(WebSocketSession session); + /** * Suspend a the incoming read events on the connection. * 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 b06e7d105ab..2f7cf8716e0 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 @@ -29,7 +29,8 @@ 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.api.extensions.Extension; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.io.payload.CloseReasonValidator; import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor; import org.eclipse.jetty.websocket.common.io.payload.NoOpValidator; @@ -59,7 +60,7 @@ public class Parser private int cursor = 0; // Frame private WebSocketFrame frame; - private WebSocketFrame priorDataFrame; + private Frame priorDataFrame; private byte lastDataOpcode; // payload specific private ByteBuffer payload; @@ -170,7 +171,7 @@ public class Parser return rsv3InUse; } - protected void notifyFrame(final WebSocketFrame f) + protected void notifyFrame(final Frame f) { if (LOG_FRAMES.isDebugEnabled()) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java index 1a5d03796e4..d1cbdf95006 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketFrame.java @@ -91,7 +91,7 @@ public class WebSocketFrame implements Frame private boolean rsv1 = false; private boolean rsv2 = false; private boolean rsv3 = false; - private byte opcode = OpCode.UNDEFINED; + protected byte opcode = OpCode.UNDEFINED; private boolean masked = false; private byte mask[]; /** @@ -141,10 +141,13 @@ public class WebSocketFrame implements Frame */ public WebSocketFrame(Frame frame) { - if(frame instanceof WebSocketFrame) { + if (frame instanceof WebSocketFrame) + { WebSocketFrame wsf = (WebSocketFrame)frame; copy(wsf,wsf.data); - } else { + } + else + { // Copy manually fin = frame.isFin(); rsv1 = frame.isRsv1(); @@ -320,6 +323,7 @@ public class WebSocketFrame implements Frame return payloadLength; } + @Override public int getPayloadStart() { if (data == null) @@ -329,7 +333,7 @@ public class WebSocketFrame implements Frame return payloadStart; } - public SendHandler getSendResult() + public SendHandler getSendHandler() { return sendHandler; } @@ -340,6 +344,7 @@ public class WebSocketFrame implements Frame return type; } + @Override public boolean hasPayload() { return ((data != null) && (payloadLength > 0)); @@ -402,20 +407,26 @@ public class WebSocketFrame implements Frame return rsv3; } - public void notifySendHandler() { - if(sendHandler == null) { - return; - } - sendHandler.setResult(new SendResult(null)); - } - - public void notifySendHandler(Throwable t) { - if(sendHandler == null) { + @Override + public void notifySendFailed(Throwable t) + { + if (sendHandler == null) + { return; } sendHandler.setResult(new SendResult(t)); } + @Override + public void notifySendSuccess() + { + if (sendHandler == null) + { + return; + } + sendHandler.setResult(new SendResult(null)); + } + /** * Get the position currently within the payload data. *

@@ -439,6 +450,7 @@ public class WebSocketFrame implements Frame * * @return the number of bytes remaining in the payload data that has not yet been written out to Network ByteBuffers. */ + @Override public int remaining() { if (data == null) @@ -463,13 +475,13 @@ public class WebSocketFrame implements Frame continuation = false; } - public WebSocketFrame setContinuation(boolean continuation) + public Frame setContinuation(boolean continuation) { this.continuation = continuation; return this; } - public WebSocketFrame setContinuationIndex(int continuationIndex) + public Frame setContinuationIndex(int continuationIndex) { this.continuationIndex = continuationIndex; return this; @@ -481,14 +493,14 @@ public class WebSocketFrame implements Frame return this; } - public WebSocketFrame setMask(byte[] maskingKey) + public Frame setMask(byte[] maskingKey) { this.mask = maskingKey; this.masked = (mask != null); return this; } - public WebSocketFrame setMasked(boolean mask) + public Frame setMasked(boolean mask) { this.masked = mask; return this; @@ -640,6 +652,9 @@ public class WebSocketFrame implements Frame b.append(rsv3?'1':'.'); b.append(",masked=").append(masked); b.append(",continuation=").append(continuation); + b.append(",payloadStart=").append(getPayloadStart()); + b.append(",remaining=").append(remaining()); + b.append(",position=").append(position()); if (sendHandler != null) { b.append(",sendHandler=").append(sendHandler); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java new file mode 100644 index 00000000000..7d4055a9421 --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java @@ -0,0 +1,243 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.Future; + +import javax.net.websocket.EncodeException; +import javax.net.websocket.RemoteEndpoint; +import javax.net.websocket.SendHandler; +import javax.net.websocket.SendResult; + +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.message.MessageOutputStream; +import org.eclipse.jetty.websocket.common.message.MessageWriter; + +/** + * Endpoint for Writing messages to the Remote websocket. + */ +public class WebSocketRemoteEndpoint implements RemoteEndpoint +{ + private static final Logger LOG = Log.getLogger(WebSocketRemoteEndpoint.class); + public final LogicalConnection connection; + public final OutgoingFrames outgoing; + public MessageOutputStream stream; + public MessageWriter writer; + + public WebSocketRemoteEndpoint(LogicalConnection connection, OutgoingFrames outgoing) + { + if (connection == null) + { + throw new IllegalArgumentException("LogicalConnection cannot be null"); + } + this.connection = connection; + this.outgoing = outgoing; + } + + public InetSocketAddress getInetSocketAddress() + { + return connection.getRemoteAddress(); + } + + @Override + public OutputStream getSendStream() throws IOException + { + if (isWriterActive()) + { + throw new IOException("Cannot get OutputStream while Writer is open"); + } + + if (isStreamActive()) + { + LOG.debug("getSendStream() -> (existing) {}",stream); + return stream; + } + + stream = new MessageOutputStream(connection,outgoing); + LOG.debug("getSendStream() -> (new) {}",stream); + return stream; + } + + @Override + public Writer getSendWriter() throws IOException + { + if (isStreamActive()) + { + throw new IOException("Cannot get Writer while OutputStream is open"); + } + + if (isWriterActive()) + { + LOG.debug("getSendWriter() -> (existing) {}",writer); + return writer; + } + + writer = new MessageWriter(connection,outgoing); + LOG.debug("getSendWriter() -> (new) {}",writer); + return writer; + } + + private boolean isStreamActive() + { + if (stream == null) + { + return false; + } + + return !stream.isClosed(); + } + + private boolean isWriterActive() + { + if (writer == null) + { + return false; + } + return !writer.isClosed(); + } + + /** + * Internal + * + * @param frame + * @return + */ + private Future sendAsyncFrame(WebSocketFrame frame) + { + try + { + connection.assertOutputOpen(); + return outgoing.outgoingFrame(frame); + } + catch (IOException e) + { + SendHandler handler = frame.getSendHandler(); + return new FailedFuture(handler, e); + } + } + + @Override + public void sendBytes(ByteBuffer data) throws IOException + { + connection.assertOutputOpen(); + if (LOG.isDebugEnabled()) + { + LOG.debug("sendBytes({})",BufferUtil.toDetailString(data)); + } + Frame frame = WebSocketFrame.binary().setPayload(data); + outgoing.outgoingFrame(frame); + } + + @Override + public Future sendBytes(ByteBuffer data, SendHandler completion) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("sendBytes({}, {})",BufferUtil.toDetailString(data),completion); + } + WebSocketFrame frame = WebSocketFrame.binary().setPayload(data); + frame.setSendHandler(completion); + return sendAsyncFrame(frame); + } + + private void sendFrame(Frame frame) + { + try + { + outgoing.outgoingFrame(frame); + } + catch (IOException e) + { + LOG.warn(e); + } + } + + @Override + public void sendObject(Object o) throws IOException, EncodeException + { + // TODO Auto-generated method stub + } + + @Override + public Future sendObject(Object o, SendHandler handler) + { + // TODO Auto-generated method stub + return null; + } + + @Override + public void sendPartialBytes(ByteBuffer partialByte, boolean isLast) throws IOException + { + Frame frame = WebSocketFrame.binary().setPayload(partialByte).setFin(isLast); + outgoing.outgoingFrame(frame); + } + + @Override + public void sendPartialString(String fragment, boolean isLast) throws IOException + { + Frame frame = WebSocketFrame.text(fragment).setFin(isLast); + outgoing.outgoingFrame(frame); + } + + @Override + public void sendPing(ByteBuffer applicationData) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("Ping with {}",BufferUtil.toDetailString(applicationData)); + } + Frame frame = WebSocketFrame.ping().setPayload(applicationData); + sendFrame(frame); + } + + @Override + public void sendPong(ByteBuffer applicationData) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("Pong with {}",BufferUtil.toDetailString(applicationData)); + } + Frame frame = WebSocketFrame.pong().setPayload(applicationData); + sendFrame(frame); + } + + @Override + public void sendString(String text) throws IOException + { + Frame frame = WebSocketFrame.text(text); + outgoing.outgoingFrame(frame); + } + + @Override + public Future sendString(String text, SendHandler completion) + { + WebSocketFrame frame = WebSocketFrame.text(text); + frame.setSendHandler(completion); + return sendAsyncFrame(frame); + } +} 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 new file mode 100644 index 00000000000..4291057191b --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java @@ -0,0 +1,510 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; + +import javax.net.websocket.ClientContainer; +import javax.net.websocket.CloseReason; +import javax.net.websocket.ContainerProvider; +import javax.net.websocket.Encoder; +import javax.net.websocket.MessageHandler; +import javax.net.websocket.RemoteEndpoint; +import javax.net.websocket.SendResult; +import javax.net.websocket.Session; + +import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.UrlEncoded; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.component.ContainerLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.SuspendToken; +import org.eclipse.jetty.websocket.api.WebSocketConnection; +import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.events.EventDriver; + +@ManagedObject +public class WebSocketSession extends ContainerLifeCycle implements Session, WebSocketConnection, IncomingFrames +{ + private static final Logger LOG = Log.getLogger(WebSocketSession.class); + private final URI requestURI; + private final EventDriver websocket; + private final LogicalConnection connection; + private Set messageHandlers = new HashSet<>(); + private List encoders = new ArrayList<>(); + private ExtensionFactory extensionFactory; + private boolean active = false; + private long maximumMessageSize; + private long inactiveTime; + private List negotiatedExtensions = new ArrayList<>(); + private String protocolVersion; + private String negotiatedSubprotocol; + private long timeout; + private Map parameterMap = new HashMap<>(); + private List extensionConfigs = new ArrayList<>(); + private WebSocketRemoteEndpoint remote; + private IncomingFrames incomingHandler; + private OutgoingFrames outgoingHandler; + private WebSocketPolicy policy; + + public WebSocketSession(URI requestURI, EventDriver websocket, LogicalConnection connection) + { + if (requestURI == null) + { + throw new RuntimeException("Request URI cannot be null"); + } + + this.requestURI = requestURI; + this.websocket = websocket; + this.connection = connection; + this.outgoingHandler = connection; + this.incomingHandler = websocket; + + // Get the parameter map (use the jetty MultiMap to do this right) + MultiMap params = new MultiMap<>(); + String query = requestURI.getQuery(); + if (StringUtil.isNotBlank(query)) + { + UrlEncoded.decodeTo(query,params,StringUtil.__UTF8); + } + + for (String name : params.keySet()) + { + List valueList = params.getValues(name); + String valueArr[] = new String[valueList.size()]; + valueArr = valueList.toArray(valueArr); + parameterMap.put(name,valueArr); + } + } + + @Override + public void addMessageHandler(MessageHandler listener) + { + messageHandlers.add(listener); + } + + @Override + public void close() throws IOException + { + connection.close(); + } + + @Override + public void close(CloseReason closeStatus) throws IOException + { + connection.close(closeStatus.getCloseCode().getCode(),closeStatus.getReasonPhrase()); + } + + @Override + public void close(int statusCode, String reason) + { + connection.close(statusCode,reason); + } + + public LogicalConnection getConnection() + { + return connection; + } + + @Override + public ClientContainer getContainer() + { + return ContainerProvider.getClientContainer(); + } + + public ExtensionFactory getExtensionFactory() + { + return extensionFactory; + } + + @Override + public long getInactiveTime() + { + return inactiveTime; + } + + @ManagedAttribute(readonly = true) + public IncomingFrames getIncomingHandler() + { + return incomingHandler; + } + + @Override + public InetSocketAddress getLocalAddress() + { + return connection.getLocalAddress(); + } + + @Override + public long getMaximumMessageSize() + { + return maximumMessageSize; + } + + @Override + public Set getMessageHandlers() + { + return Collections.unmodifiableSet(messageHandlers); + } + + @Override + public List getNegotiatedExtensions() + { + return negotiatedExtensions; + } + + @Override + public String getNegotiatedSubprotocol() + { + return negotiatedSubprotocol; + } + + @ManagedAttribute(readonly = true) + public OutgoingFrames getOutgoingHandler() + { + return outgoingHandler; + } + + @Override + public Map getParameterMap() + { + return parameterMap; + } + + @Override + public WebSocketPolicy getPolicy() + { + return policy; + } + + @Override + public String getProtocolVersion() + { + return protocolVersion; + } + + @Override + public String getQueryString() + { + return getRequestURI().getQuery(); + } + + @Override + public RemoteEndpoint getRemote() + { + if (!isOpen()) + { + throw new WebSocketException("Session has not been opened yet"); + } + return remote; + } + + @Override + public RemoteEndpoint getRemote(Class c) + { + // TODO Auto-generated method stub + return null; + } + + @Override + public InetSocketAddress getRemoteAddress() + { + return remote.getInetSocketAddress(); + } + + @Override + public URI getRequestURI() + { + return requestURI; + } + + @Override + public String getSubProtocol() + { + return getNegotiatedSubprotocol(); + } + + /** + * The timeout in seconds + */ + @Override + public long getTimeout() + { + return timeout; + } + + /** + * Incoming Errors from Parser + */ + @Override + public void incomingError(WebSocketException e) + { + if (connection.isInputClosed()) + { + return; // input is closed + } + // Forward Errors to User WebSocket Object + websocket.incomingError(e); + } + + /** + * Incoming Raw Frames from Parser + */ + @Override + public void incomingFrame(Frame frame) + { + if (connection.isInputClosed()) + { + return; // input is closed + } + + // Forward Frames Through Extension List + incomingHandler.incomingFrame(frame); + } + + @Override + public boolean isActive() + { + return active; + } + + @Override + public boolean isOpen() + { + return isActive(); + } + + @Override + public boolean isSecure() + { + return getRequestURI().getScheme().equalsIgnoreCase("wss"); + } + + /** + * Open/Activate the session + * + * @throws IOException + */ + public void open() + { + if (isOpen()) + { + throw new WebSocketException("Cannot Open WebSocketSession, Already open"); + } + + // Initialize extensions + LOG.debug("Extension Configs={}",extensionConfigs); + List extensions = new ArrayList<>(); + for (ExtensionConfig config : extensionConfigs) + { + Extension ext = extensionFactory.newInstance(config); + extensions.add(ext); + LOG.debug("Adding Extension: {}",ext); + } + + // Wire up Extensions + if (extensions.size() > 0) + { + Iterator extIter; + + // Connect outgoings + extIter = extensions.iterator(); + while (extIter.hasNext()) + { + Extension ext = extIter.next(); + ext.setNextOutgoingFrames(outgoingHandler); + outgoingHandler = ext; + } + + // Connect incomings + Collections.reverse(extensions); + extIter = extensions.iterator(); + while (extIter.hasNext()) + { + Extension ext = extIter.next(); + ext.setNextIncomingFrames(incomingHandler); + incomingHandler = ext; + } + } + + addBean(incomingHandler); + addBean(outgoingHandler); + + // Connect remote + remote = new WebSocketRemoteEndpoint(connection,outgoingHandler); + + // Activate Session + this.active = true; + + // Open WebSocket + websocket.setSession(this); + websocket.onConnect(); + + if (LOG.isDebugEnabled()) + { + LOG.debug("{}",dump()); + } + } + + @Override + public void ping(ByteBuffer buf) throws IOException + { + remote.sendPing(buf); + } + + @Override + public void removeMessageHandler(MessageHandler listener) + { + messageHandlers.remove(listener); + } + + public void setActive(boolean active) + { + this.active = active; + } + + @Override + public void setEncoders(List encoders) + { + this.encoders.clear(); + if (encoders != null) + { + encoders.addAll(encoders); + } + } + + public void setExtensionFactory(ExtensionFactory extensionFactory) + { + this.extensionFactory = extensionFactory; + } + + @Override + public void setMaximumMessageSize(long length) + { + this.maximumMessageSize = length; + } + + public void setNegotiatedExtensionConfigs(List extensions) + { + this.negotiatedExtensions.clear(); + this.extensionConfigs.clear(); + + for (ExtensionConfig config : extensions) + { + this.extensionConfigs.add(config); + this.negotiatedExtensions.add(config.getParameterizedName()); + } + } + + public void setNegotiatedExtensions(List negotiatedExtensions) + { + this.negotiatedExtensions = negotiatedExtensions; + + this.extensionConfigs.clear(); + for (String negotiatedExtension : negotiatedExtensions) + { + this.extensionConfigs.add(ExtensionConfig.parse(negotiatedExtension)); + } + } + + public void setNegotiatedSubprotocol(String negotiatedSubprotocol) + { + this.negotiatedSubprotocol = negotiatedSubprotocol; + } + + public void setOutgoingHandler(OutgoingFrames outgoing) + { + this.outgoingHandler = outgoing; + } + + public void setPolicy(WebSocketPolicy policy) + { + this.policy = policy; + } + + /** + * Set the timeout in seconds + */ + @Override + public void setTimeout(long seconds) + { + this.timeout = seconds; + } + + @Override + public SuspendToken suspend() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("WebSocketSession["); + builder.append("websocket=").append(websocket); + builder.append(",connection=").append(connection); + builder.append(",remote=").append(remote); + builder.append(",incoming=").append(incomingHandler); + builder.append(",outgoing=").append(outgoingHandler); + builder.append("]"); + return builder.toString(); + } + + @Override + public Future write(byte[] buf, int offset, int len) throws IOException + { + return remote.sendBytes(ByteBuffer.wrap(buf,offset,len),null); + } + + @Override + public Future write(ByteBuffer buffer) throws IOException + { + return remote.sendBytes(buffer,null); + } + + @Override + public Future write(String message) throws IOException + { + return remote.sendString(message,null); + } +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java index e2f3838f559..96966cfa527 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java @@ -31,17 +31,16 @@ import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; +import org.eclipse.jetty.websocket.common.WebSocketSession; /** * EventDriver is the main interface between the User's WebSocket POJO and the internal jetty implementation of WebSocket. */ -public abstract class EventDriver extends AbstractJettyFrameHandler implements IncomingFrames +public abstract class EventDriver implements IncomingFrames { protected final Logger LOG; protected final WebSocketPolicy policy; @@ -50,7 +49,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I public EventDriver(WebSocketPolicy policy, Object websocket) { - super(null); this.policy = policy; this.websocket = websocket; this.LOG = Log.getLogger(websocket.getClass()); @@ -66,12 +64,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I return session; } - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - incomingFrame(frame); - } - @Override public final void incomingError(WebSocketException e) { @@ -90,7 +82,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { if (LOG.isDebugEnabled()) { @@ -101,7 +93,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I try { - switch (frame.getOpCode()) + switch (frame.getType().getOpCode()) { case OpCode.CLOSE: { @@ -115,27 +107,21 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I session.close(close.getStatusCode(),close.getReason()); // process handshake - session.onCloseHandshake(true,close); + session.getConnection().onCloseHandshake(true,close); return; } case OpCode.PING: { - WebSocketFrame pong = new WebSocketFrame(OpCode.PONG); + ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength()); if (frame.getPayloadLength() > 0) { // Copy payload - ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength()); BufferUtil.clearToFill(pongBuf); BufferUtil.put(frame.getPayload(),pongBuf); BufferUtil.flipToFlush(pongBuf,0); - pong.setPayload(pongBuf); - if (LOG.isDebugEnabled()) - { - LOG.debug("Pong with {}",BufferUtil.toDetailString(pongBuf)); - } } - session.outgoingFrame(pong); + session.getRemote().sendPong(pongBuf); break; } case OpCode.BINARY: diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java index 0ea2455cdb6..38d3610e29a 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java @@ -18,20 +18,37 @@ package org.eclipse.jetty.websocket.common.extensions; -import java.util.Map; +import java.io.IOException; +import java.util.concurrent.Future; + +import javax.net.websocket.SendResult; import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.api.WebSocketConnection; +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.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.LogicalConnection; public abstract class AbstractExtension implements Extension { + private final Logger log; private WebSocketPolicy policy; private ByteBufferPool bufferPool; private ExtensionConfig config; - private WebSocketConnection connection; + private LogicalConnection connection; + private OutgoingFrames nextOutgoing; + private IncomingFrames nextIncoming; + + public AbstractExtension() + { + log = Log.getLogger(this.getClass()); + } public ByteBufferPool getBufferPool() { @@ -44,7 +61,7 @@ public abstract class AbstractExtension implements Extension return config; } - public WebSocketConnection getConnection() + public LogicalConnection getConnection() { return connection; } @@ -55,17 +72,17 @@ public abstract class AbstractExtension implements Extension return config.getName(); } - @Override - public Map getParameters() - { - return config.getParameters(); - } - public WebSocketPolicy getPolicy() { return policy; } + @Override + public void incomingError(WebSocketException e) + { + nextIncomingError(e); + } + /** * Used to indicate that the extension makes use of the RSV1 bit of the base websocket framing. *

@@ -122,6 +139,23 @@ public abstract class AbstractExtension implements Extension return false; } + protected void nextIncomingError(WebSocketException e) + { + this.nextIncoming.incomingError(e); + } + + protected void nextIncomingFrame(Frame frame) + { + log.debug("nextIncomingFrame({})",frame); + this.nextIncoming.incomingFrame(frame); + } + + protected Future nextOutgoingFrame(Frame frame) throws IOException + { + log.debug("nextOutgoingFrame({})",frame); + return this.nextOutgoing.outgoingFrame(frame); + } + public void setBufferPool(ByteBufferPool bufferPool) { this.bufferPool = bufferPool; @@ -132,11 +166,23 @@ public abstract class AbstractExtension implements Extension this.config = config; } - public void setConnection(WebSocketConnection connection) + public void setConnection(LogicalConnection connection) { this.connection = connection; } + @Override + public void setNextIncomingFrames(IncomingFrames nextIncoming) + { + this.nextIncoming = nextIncoming; + } + + @Override + public void setNextOutgoingFrames(OutgoingFrames nextOutgoing) + { + this.nextOutgoing = nextOutgoing; + } + public void setPolicy(WebSocketPolicy policy) { this.policy = policy; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractJettyFrameHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractJettyFrameHandler.java deleted file mode 100644 index f4f9fa5d647..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractJettyFrameHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.common.WebSocketFrame; - -public abstract class AbstractJettyFrameHandler extends FrameHandler -{ - private Logger log; - - public AbstractJettyFrameHandler(FrameHandler nextHandler) - { - super(nextHandler); - log = Log.getLogger(this.getClass()); - } - - /** - * Incoming for javax.net.websocket based frames. - *

- * Note: As of 006EDR of the JavaWebSocket API is, the {@link javax.net.websocket.extensions.Frame} interface is insufficient to handle the intricacies of - * Extensions. The implementations of {@link javax.net.websocket.extensions.Extension} within Jetty will attempt to cast to - * {@link org.eclipse.jetty.websocket.common.WebSocketFrame} to handle only jetty managed/created WebSocketFrames. - */ - @Override - public final void handleFrame(javax.net.websocket.extensions.Frame f) - { - if (f instanceof WebSocketFrame) - { - handleJettyFrame((WebSocketFrame)f); - } - else - { - // [006EDR] - throw new RuntimeException("Unsupported, Frame type [" + f.getClass().getName() + "] must be an instanceof [" + WebSocketFrame.class.getName() - + "]"); - } - } - - public abstract void handleJettyFrame(WebSocketFrame frame); - - protected void nextJettyHandler(WebSocketFrame frame) - { - FrameHandler next = getNextHandler(); - if (next == null) - { - log.debug("No next handler (ending chain) {}",frame); - return; - } - if (log.isDebugEnabled()) - { - log.debug("nextHandler({}) -> {}",frame,next); - } - next.handleFrame(frame); - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/IncomingFrameHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/IncomingFrameHandler.java deleted file mode 100644 index a54df08c29b..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/IncomingFrameHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions; - -import javax.net.websocket.extensions.FrameHandler; - -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.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; - -/** - * Route jetty internal frames into extension {@link FrameHandler} concept. - */ -public class IncomingFrameHandler implements IncomingFrames -{ - private static final Logger LOG = Log.getLogger(IncomingFrameHandler.class); - private FrameHandler extHandler; - - public IncomingFrameHandler(FrameHandler nextHandler) - { - this.extHandler = nextHandler; - } - - @Override - public void incomingError(WebSocketException e) - { - LOG.info("Not able to forward error into extension stack",e); - } - - @Override - public void incomingFrame(WebSocketFrame frame) - { - extHandler.handleFrame(frame); - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionRegistry.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionFactory.java similarity index 72% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionRegistry.java rename to jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionFactory.java index 3a2e2cffe09..e73e5744270 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionRegistry.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/WebSocketExtensionFactory.java @@ -25,23 +25,29 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; +import org.eclipse.jetty.websocket.common.extensions.compress.FrameCompressionExtension; +import org.eclipse.jetty.websocket.common.extensions.compress.MessageCompressionExtension; +import org.eclipse.jetty.websocket.common.extensions.fragment.FragmentExtension; +import org.eclipse.jetty.websocket.common.extensions.identity.IdentityExtension; -public class WebSocketExtensionRegistry extends ExtensionFactory +public class WebSocketExtensionFactory extends ExtensionFactory { private WebSocketPolicy policy; private ByteBufferPool bufferPool; - public WebSocketExtensionRegistry(WebSocketPolicy policy, ByteBufferPool bufferPool) + public WebSocketExtensionFactory(WebSocketPolicy policy, ByteBufferPool bufferPool) { + super(); this.policy = policy; this.bufferPool = bufferPool; - // FIXME this.registry.put("identity",IdentityExtension.class); - // FIXME this.registry.put("fragment",FragmentExtension.class); - // FIXME this.registry.put("x-webkit-deflate-frame",WebkitDeflateFrameExtension.class); - // FIXME this.registry.put("permessage-compress",PerMessageCompressionExtension.class); + register("identity",IdentityExtension.class); + register("fragment",FragmentExtension.class); + register("x-webkit-deflate-frame",FrameCompressionExtension.class); + register("permessage-compress",MessageCompressionExtension.class); } + @Override public Extension newInstance(ExtensionConfig config) { if (config == null) @@ -55,14 +61,12 @@ public class WebSocketExtensionRegistry extends ExtensionFactory return null; } - Extension registeredExt = getExtension(name); - if (registeredExt == null) + Class extClass = getExtension(name); + if (extClass == null) { return null; } - Class extClass = registeredExt.getClass(); - try { Extension ext = extClass.newInstance(); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressFrameHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressFrameHandler.java deleted file mode 100644 index 1edbc6b75fc..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressFrameHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - -import java.nio.ByteBuffer; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; - -/** - * Compress individual data frames. - */ -public class CompressFrameHandler extends AbstractJettyFrameHandler -{ - private final CompressionMethod method; - private final ByteBufferPool bufferPool; - - public CompressFrameHandler(FrameHandler outgoing, DeflateCompressionMethod method, ByteBufferPool bufferPool) - { - super(outgoing); - this.method = method; - this.bufferPool = bufferPool; - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - if (frame.getType().isControl()) - { - // skip, cannot compress control frames. - nextJettyHandler(frame); - return; - } - - ByteBuffer data = frame.getPayload(); - try - { - // deflate data - method.compress().input(data); - while (!method.compress().isDone()) - { - ByteBuffer buf = method.compress().process(); - WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf); - out.setRsv1(true); - if (!method.compress().isDone()) - { - out.setFin(false); - } - - nextJettyHandler(out); - } - - // reset on every frame. - method.compress().end(); - } - finally - { - // free original data buffer - bufferPool.release(data); - } - } -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressMessageHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressMessageHandler.java deleted file mode 100644 index 8969f7fbe67..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressMessageHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - -import java.nio.ByteBuffer; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; - -/** - * Compress entire message (regardless of number of frames). - */ -public class CompressMessageHandler extends AbstractJettyFrameHandler -{ - private final CompressionMethod method; - private final ByteBufferPool bufferPool; - - public CompressMessageHandler(FrameHandler nextHandler, CompressionMethod method, ByteBufferPool bufferPool) - { - super(nextHandler); - this.method = method; - this.bufferPool = bufferPool; - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - if (frame.getType().isControl()) - { - // skip, cannot compress control frames. - nextJettyHandler(frame); - return; - } - - ByteBuffer data = frame.getPayload(); - try - { - // deflate data - method.compress().input(data); - while (!method.compress().isDone()) - { - ByteBuffer buf = method.compress().process(); - WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf); - out.setRsv1(true); - if (!method.compress().isDone()) - { - out.setFin(false); - nextJettyHandler(out); - } - else - { - nextJettyHandler(out); - } - } - - // reset only at end of message - if (frame.isFin()) - { - method.compress().end(); - } - } - finally - { - // free original data buffer - bufferPool.release(data); - } - } - -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressFrameHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressFrameHandler.java deleted file mode 100644 index d0d3880af0f..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressFrameHandler.java +++ /dev/null @@ -1,84 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - -import java.nio.ByteBuffer; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; - -/** - * Handler for Decompress of individual Data frames. - */ -public class DecompressFrameHandler extends AbstractJettyFrameHandler -{ - private static final Logger LOG = Log.getLogger(DecompressFrameHandler.class); - private final CompressionMethod method; - private final ByteBufferPool bufferPool; - - public DecompressFrameHandler(FrameHandler incoming, DeflateCompressionMethod method, ByteBufferPool bufferPool) - { - super(incoming); - this.method = method; - this.bufferPool = bufferPool; - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - if (frame.getType().isControl() || !frame.isRsv1()) - { - // Cannot modify incoming control frames or ones with RSV1 set. - nextJettyHandler(frame); - return; - } - - LOG.debug("Decompressing Frame: {}",frame); - - ByteBuffer data = frame.getPayload(); - try - { - method.decompress().input(data); - while (!method.decompress().isDone()) - { - ByteBuffer uncompressed = method.decompress().process(); - WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed); - if (!method.decompress().isDone()) - { - out.setFin(false); - } - out.setRsv1(false); // Unset RSV1 on decompressed frame - nextJettyHandler(out); - } - - // reset on every frame. - method.decompress().end(); - } - finally - { - // release original buffer (no longer needed) - bufferPool.release(data); - } - } -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressMessageHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressMessageHandler.java deleted file mode 100644 index 6f00fdceee3..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DecompressMessageHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - -import java.nio.ByteBuffer; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; - -/** - * Decompress entire message (regardless of number of frames) - */ -public class DecompressMessageHandler extends AbstractJettyFrameHandler -{ - private CompressionMethod method; - private final ByteBufferPool bufferPool; - - public DecompressMessageHandler(FrameHandler nextHandler, CompressionMethod method, ByteBufferPool bufferPool) - { - super(nextHandler); - this.method = method; - this.bufferPool = bufferPool; - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - if (frame.getType().isControl() || !frame.isRsv1()) - { - // Cannot modify incoming control frames or ones with RSV1 set. - nextJettyHandler(frame); - return; - } - - ByteBuffer data = frame.getPayload(); - try - { - method.decompress().input(data); - while (!method.decompress().isDone()) - { - ByteBuffer uncompressed = method.decompress().process(); - if (uncompressed == null) - { - continue; - } - WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed); - if (!method.decompress().isDone()) - { - out.setFin(false); - } - out.setRsv1(false); // Unset RSV1 on decompressed frame - nextJettyHandler(out); - } - - // reset only at the end of a message. - if (frame.isFin()) - { - method.decompress().end(); - } - } - finally - { - // release original buffer (no longer needed) - bufferPool.release(data); - } - } -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/FrameCompressionExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/FrameCompressionExtension.java new file mode 100644 index 00000000000..7dcea705831 --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/FrameCompressionExtension.java @@ -0,0 +1,151 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common.extensions.compress; + + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.Future; + +import javax.net.websocket.SendResult; + +import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; + +/** + * Implementation of the x-webkit-deflate-frame extension seen out + * in the wild. + */ +public class FrameCompressionExtension extends AbstractExtension +{ + private DeflateCompressionMethod method; + + @Override + public void incomingFrame(Frame frame) + { + if (frame.getType().isControl() || !frame.isRsv1()) + { + // Cannot modify incoming control frames or ones with RSV1 set. + nextIncomingFrame(frame); + return; + } + + ByteBuffer data = frame.getPayload(); + try + { + method.decompress().input(data); + while (!method.decompress().isDone()) + { + ByteBuffer uncompressed = method.decompress().process(); + WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed); + if (!method.decompress().isDone()) + { + out.setFin(false); + } + out.setRsv1(false); // Unset RSV1 on decompressed frame + nextIncomingFrame(out); + } + + // reset on every frame. + method.decompress().end(); + } + finally + { + // release original buffer (no longer needed) + getBufferPool().release(data); + } + } + + /** + * Indicates use of RSV1 flag for indicating deflation is in use. + *

+ * Also known as the "COMP" framing header bit + */ + @Override + public boolean isRsv1User() + { + return true; + } + + /** + * Indicate that this extensions is now responsible for TEXT Data Frame compliance to the WebSocket spec. + */ + @Override + public boolean isTextDataDecoder() + { + return true; + } + + @Override + public Future outgoingFrame(Frame frame) throws IOException + { + if (frame.getType().isControl()) + { + // skip, cannot compress control frames. + return nextOutgoingFrame(frame); + } + + Future future = null; + + ByteBuffer data = frame.getPayload(); + try + { + // deflate data + method.compress().input(data); + while (!method.compress().isDone()) + { + ByteBuffer buf = method.compress().process(); + WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf); + out.setRsv1(true); + if (!method.compress().isDone()) + { + out.setFin(false); + } + + future = nextOutgoingFrame(out); + } + + // reset on every frame. + method.compress().end(); + } + finally + { + // free original data buffer + getBufferPool().release(data); + } + + return future; + } + + @Override + public void setConfig(ExtensionConfig config) + { + super.setConfig(config); + + method = new DeflateCompressionMethod(); + } + + @Override + public String toString() + { + return this.getClass().getSimpleName() + "[]"; + } +} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/MessageCompressionExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/MessageCompressionExtension.java new file mode 100644 index 00000000000..db79726a0be --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/MessageCompressionExtension.java @@ -0,0 +1,168 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common.extensions.compress; + + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.Future; + +import javax.net.websocket.SendResult; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; + +/** + * Per Message Compression extension for WebSocket. + *

+ * Attempts to follow draft-ietf-hybi-permessage-compression-01 + */ +public class MessageCompressionExtension extends AbstractExtension +{ + private static final Logger LOG = Log.getLogger(MessageCompressionExtension.class); + + private CompressionMethod method; + + @Override + public void incomingFrame(Frame frame) + { + if (frame.getType().isControl() || !frame.isRsv1()) + { + // Cannot modify incoming control frames or ones with RSV1 set. + nextIncomingFrame(frame); + return; + } + + ByteBuffer data = frame.getPayload(); + try + { + method.decompress().input(data); + while (!method.decompress().isDone()) + { + ByteBuffer uncompressed = method.decompress().process(); + if (uncompressed == null) + { + continue; + } + WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed); + if (!method.decompress().isDone()) + { + out.setFin(false); + } + out.setRsv1(false); // Unset RSV1 on decompressed frame + nextIncomingFrame(out); + } + + // reset only at the end of a message. + if (frame.isFin()) + { + method.decompress().end(); + } + } + finally + { + // release original buffer (no longer needed) + getBufferPool().release(data); + } + } + + /** + * Indicates use of RSV1 flag for indicating deflation is in use. + */ + @Override + public boolean isRsv1User() + { + return true; + } + + @Override + public boolean isTextDataDecoder() + { + // this extension is responsible for text data frames + return true; + } + + @Override + public Future outgoingFrame(Frame frame) throws IOException + { + if (frame.getType().isControl()) + { + // skip, cannot compress control frames. + return nextOutgoingFrame(frame); + } + + Future future = null; + + ByteBuffer data = frame.getPayload(); + try + { + // deflate data + method.compress().input(data); + while (!method.compress().isDone()) + { + ByteBuffer buf = method.compress().process(); + WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf); + out.setRsv1(true); + if (!method.compress().isDone()) + { + out.setFin(false); + future = nextOutgoingFrame(out); + } + else + { + future = nextOutgoingFrame(out); + } + } + + // reset only at end of message + if (frame.isFin()) + { + method.compress().end(); + } + } + finally + { + // free original data buffer + getBufferPool().release(data); + } + + return future; + } + + @Override + public void setConfig(ExtensionConfig config) + { + super.setConfig(config); + + String methodOptions = config.getParameter("method","deflate"); + LOG.debug("Method requested: {}",methodOptions); + + method = new DeflateCompressionMethod(); + } + + @Override + public String toString() + { + return String.format("%s[method=%s]",this.getClass().getSimpleName(),method); + } +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtension.java deleted file mode 100644 index 8925f080097..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtension.java +++ /dev/null @@ -1,82 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - - -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; -import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; - -/** - * Per Message Compression extension for WebSocket. - *

- * Attempts to follow draft-ietf-hybi-permessage-compression-01 - */ -public class PerMessageCompressionExtension extends AbstractExtension -{ - private static final Logger LOG = Log.getLogger(PerMessageCompressionExtension.class); - - private CompressionMethod method; - - @Override - public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming) - { - return new DecompressMessageHandler(incoming,method,getBufferPool()); - } - - @Override - public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing) - { - return new CompressMessageHandler(outgoing,method,getBufferPool()); - } - - /** - * Indicates use of RSV1 flag for indicating deflation is in use. - */ - @Override - public boolean isRsv1User() - { - return true; - } - - @Override - public boolean isTextDataDecoder() - { - // this extension is responsible for text data frames - return true; - } - - @Override - public void setConfig(ExtensionConfig config) - { - super.setConfig(config); - - String methodOptions = config.getParameter("method","deflate"); - LOG.debug("Method requested: {}",methodOptions); - - method = new DeflateCompressionMethod(); - } - - @Override - public String toString() - { - return String.format("%s[method=%s]",this.getClass().getSimpleName(),method); - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtension.java deleted file mode 100644 index 64f7e97771f..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtension.java +++ /dev/null @@ -1,78 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.compress; - - -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; -import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; - -/** - * Implementation of the x-webkit-deflate-frame extension seen out - * in the wild. - */ -public class WebkitDeflateFrameExtension extends AbstractExtension -{ - private DeflateCompressionMethod method; - - @Override - public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming) - { - return new DecompressFrameHandler(incoming,method,getBufferPool()); - } - - @Override - public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing) - { - return new CompressFrameHandler(outgoing,method,getBufferPool()); - } - - /** - * Indicates use of RSV1 flag for indicating deflation is in use. - *

- * Also known as the "COMP" framing header bit - */ - @Override - public boolean isRsv1User() - { - return true; - } - - /** - * Indicate that this extensions is now responsible for TEXT Data Frame compliance to the WebSocket spec. - */ - @Override - public boolean isTextDataDecoder() - { - return true; - } - - @Override - public void setConfig(ExtensionConfig config) - { - super.setConfig(config); - - method = new DeflateCompressionMethod(); - } - - @Override - public String toString() - { - return this.getClass().getSimpleName() + "[]"; - } -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java index ecd785bdab9..2fc942a75e8 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java @@ -19,9 +19,18 @@ package org.eclipse.jetty.websocket.common.extensions.fragment; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.Future; + +import javax.net.websocket.SendResult; + +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.OpCode; +import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; -import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler; /** * Fragment Extension @@ -31,16 +40,72 @@ public class FragmentExtension extends AbstractExtension private int maxLength = -1; @Override - public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming) + public void incomingError(WebSocketException e) { - // pass through handler - return new PassthruFrameHandler(incoming); + // Pass thru + nextIncomingError(e); } @Override - public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing) + public void incomingFrame(Frame frame) { - return new FragmentHandler(outgoing,maxLength); + // Pass thru + nextIncomingFrame(frame); + } + + @Override + public Future outgoingFrame(Frame frame) throws IOException + { + if (frame.getType().isControl()) + { + // Cannot fragment Control Frames + return nextOutgoingFrame(frame); + } + + int length = frame.getPayloadLength(); + + byte opcode = frame.getType().getOpCode(); // original opcode + ByteBuffer payload = frame.getPayload().slice(); + int originalLimit = payload.limit(); + int currentPosition = payload.position(); + + if (maxLength <= 0) + { + // output original frame + return nextOutgoingFrame(frame); + } + + boolean continuation = false; + + // break apart payload based on maxLength rules + while (length > maxLength) + { + WebSocketFrame frag = new WebSocketFrame(frame); + frag.setOpCode(opcode); + frag.setFin(false); // always false here + frag.setContinuation(continuation); + payload.position(currentPosition); + payload.limit(Math.min(payload.position() + maxLength,originalLimit)); + frag.setPayload(payload); + + nextOutgoingFrame(frag); + + length -= maxLength; + opcode = OpCode.CONTINUATION; + continuation = true; + currentPosition = payload.limit(); + } + + // write remaining + WebSocketFrame frag = new WebSocketFrame(frame); + frag.setOpCode(opcode); + frag.setFin(frame.isFin()); // use original fin + frag.setContinuation(continuation); + payload.position(currentPosition); + payload.limit(originalLimit); + frag.setPayload(payload); + + return nextOutgoingFrame(frag); } @Override diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentHandler.java deleted file mode 100644 index 4a7d6515b58..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.eclipse.jetty.websocket.common.extensions.fragment; - -import java.nio.ByteBuffer; - -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; - -/** - * Handler to break apart the frames into multiple smaller frames. - */ -public class FragmentHandler extends AbstractJettyFrameHandler -{ - private final int maxLength; - - /** - * @param fragmentExtension - */ - public FragmentHandler(FrameHandler nextHandler, int maxLength) - { - super(nextHandler); - this.maxLength = maxLength; - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - if (frame.getType().isControl()) - { - // Cannot fragment Control Frames - nextJettyHandler(frame); - return; - } - - int length = frame.getPayloadLength(); - - byte opcode = frame.getType().getOpCode(); // original opcode - ByteBuffer payload = frame.getPayload().slice(); - int originalLimit = payload.limit(); - int currentPosition = payload.position(); - - if (maxLength <= 0) - { - // output original frame - nextJettyHandler(frame); - return; - } - - boolean continuation = false; - - // break apart payload based on maxLength rules - while (length > maxLength) - { - WebSocketFrame frag = new WebSocketFrame(frame); - frag.setOpCode(opcode); - frag.setFin(false); // always false here - frag.setContinuation(continuation); - payload.position(currentPosition); - payload.limit(Math.min(payload.position() + maxLength,originalLimit)); - frag.setPayload(payload); - - nextJettyHandler(frag); - - length -= maxLength; - opcode = OpCode.CONTINUATION; - continuation = true; - currentPosition = payload.limit(); - } - - // write remaining - WebSocketFrame frag = new WebSocketFrame(frame); - frag.setOpCode(opcode); - frag.setFin(frame.isFin()); // use original fin - frag.setContinuation(continuation); - payload.position(currentPosition); - payload.limit(originalLimit); - frag.setPayload(payload); - - nextJettyHandler(frag); - } -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java index 9b61e7792b4..55931962dc2 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java @@ -18,25 +18,40 @@ package org.eclipse.jetty.websocket.common.extensions.identity; +import java.io.IOException; +import java.util.concurrent.Future; + +import javax.net.websocket.SendResult; + import org.eclipse.jetty.util.QuotedStringTokenizer; +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; -import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler; public class IdentityExtension extends AbstractExtension { private String id; @Override - public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming) + public void incomingError(WebSocketException e) { - return new PassthruFrameHandler(incoming); + // pass through + nextIncomingError(e); } @Override - public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing) + public void incomingFrame(Frame frame) { - return new PassthruFrameHandler(outgoing); + // pass through + nextIncomingFrame(frame); + } + + @Override + public Future outgoingFrame(Frame frame) throws IOException + { + // pass through + return nextOutgoingFrame(frame); } @Override diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/AbstractMuxExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/AbstractMuxExtension.java index 1a42b10cdec..25ed52a2e0f 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/AbstractMuxExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/AbstractMuxExtension.java @@ -18,9 +18,13 @@ package org.eclipse.jetty.websocket.common.extensions.mux; -import javax.net.websocket.extensions.FrameHandler; +import java.io.IOException; +import java.util.concurrent.Future; -import org.eclipse.jetty.websocket.api.WebSocketConnection; +import javax.net.websocket.SendResult; + +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; /** @@ -40,19 +44,20 @@ public abstract class AbstractMuxExtension extends AbstractExtension public abstract void configureMuxer(Muxer muxer); @Override - public FrameHandler createIncomingFrameHandler(FrameHandler incoming) + public void incomingFrame(Frame frame) { - return new MuxerIncomingFrameHandler(incoming,muxer); + this.muxer.incomingFrame(frame); } @Override - public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing) + public Future outgoingFrame(Frame frame) throws IOException { - return new MuxerOutgoingFrameHandler(outgoing,muxer); + /* do nothing */ + return null; } @Override - public void setConnection(WebSocketConnection connection) + public void setConnection(LogicalConnection connection) { super.setConnection(connection); if (muxer != null) diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxChannel.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxChannel.java index f964e3912af..3996253b008 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxChannel.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxChannel.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; import java.nio.ByteBuffer; -import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; @@ -35,20 +34,18 @@ import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.ConnectionState; +import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.InternalConnection; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; +import org.eclipse.jetty.websocket.common.WebSocketSession; /** * MuxChannel, acts as WebSocketConnection for specific sub-channel. */ -public class MuxChannel implements WebSocketConnection, InternalConnection, IncomingFrames, OutgoingFrames, SuspendToken +public class MuxChannel implements WebSocketConnection, LogicalConnection, IncomingFrames, SuspendToken { private static final Logger LOG = Log.getLogger(MuxChannel.class); @@ -76,6 +73,20 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco this.outputClosed = new AtomicBoolean(false); } + @Override + public void assertInputOpen() throws IOException + { + // TODO Auto-generated method stub + + } + + @Override + public void assertOutputOpen() throws IOException + { + // TODO Auto-generated method stub + + } + @Override public void close() { @@ -97,12 +108,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco } } - @Override - public void configureFromExtensions(List extensions) - { - /* ignore */ - } - @Override public void disconnect() { @@ -141,6 +146,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco return null; } + @Override public WebSocketSession getSession() { return session; @@ -171,7 +177,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco * Incoming frames from Muxer */ @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { incoming.incomingFrame(frame); } @@ -250,7 +256,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco * Frames destined for the Muxer */ @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { return muxer.output(channelId,frame); } @@ -259,9 +265,9 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco * Ping frame destined for the Muxer */ @Override - public Future ping(byte[] payload) throws IOException + public void ping(ByteBuffer buf) throws IOException { - return outgoingFrame(WebSocketFrame.ping().setPayload(payload)); + outgoingFrame(WebSocketFrame.ping().setPayload(buf)); } @Override @@ -274,7 +280,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco } @Override - public void setIncoming(IncomingFrames incoming) + public void setNextIncomingFrames(IncomingFrames incoming) { this.incoming = incoming; } @@ -283,7 +289,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco public void setSession(WebSocketSession session) { this.session = session; - session.setOutgoing(this); + // session.setOutgoing(this); } public void setSubProtocol(String subProtocol) @@ -299,40 +305,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco return this; } - public void wireUpExtensions(List extensions) - { - // Start with default routing. - incoming = session; - OutgoingFrames outgoing = this; - - if (extensions != null) - { - // FIXME - // Iterator extIter; - // // Connect outgoings - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // AbstractExtension ext = extIter.next(); - // ext.setNextOutgoingFrames(outgoing); - // outgoing = ext; - // } - // - // // Connect incomings - // Collections.reverse(extensions); - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // AbstractExtension ext = extIter.next(); - // ext.setNextIncomingFrames(incoming); - // incoming = ext; - // } - } - - // set outgoing - this.session.setOutgoing(outgoing); - } - /** * Generate a binary message, destined for Muxer */ diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxGenerator.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxGenerator.java index 8fde2aff5d6..1f178b433fd 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxGenerator.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxGenerator.java @@ -27,13 +27,14 @@ import javax.net.websocket.SendResult; import org.eclipse.jetty.io.ArrayByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRequest; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; /** * Generate Mux frames destined for the physical connection. @@ -56,7 +57,7 @@ public class MuxGenerator this.bufferPool = bufferPool; } - public Future generate(long channelId, WebSocketFrame frame) throws IOException + public Future generate(long channelId, Frame frame) throws IOException { ByteBuffer muxPayload = bufferPool.acquire(frame.getPayloadLength() + DATA_FRAME_OVERHEAD,false); BufferUtil.flipToFill(muxPayload); @@ -67,7 +68,7 @@ public class MuxGenerator b |= (byte)(frame.isRsv1()?0x40:0x00); // rsv1 b |= (byte)(frame.isRsv2()?0x20:0x00); // rsv2 b |= (byte)(frame.isRsv3()?0x10:0x00); // rsv3 - b |= (byte)(frame.getOpCode() & 0x0F); // opcode + b |= (byte)(frame.getType().getOpCode() & 0x0F); // opcode muxPayload.put(b); BufferUtil.put(frame.getPayload(),muxPayload); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParser.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParser.java index 852836e2b2b..a2c9403760b 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParser.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParser.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRequest; @@ -67,7 +68,7 @@ public class MuxParser * @param frame * the WebSocketFrame to parse for mux payload */ - public synchronized void parse(WebSocketFrame frame) + public synchronized void parse(Frame frame) { if (events == null) { @@ -80,7 +81,7 @@ public class MuxParser return; // nothing to parse } - if (frame.getOpCode() != OpCode.BINARY) + if (frame.getType().getOpCode() != OpCode.BINARY) { LOG.debug("Not a binary opcode (base frame), skipping"); return; // not a binary opcode diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/Muxer.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/Muxer.java index dc09c7c148a..f0ae3a62c44 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/Muxer.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/Muxer.java @@ -32,10 +32,14 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.UpgradeRequest; +import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient; import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer; @@ -44,8 +48,6 @@ import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRespons import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; /** * Muxer responsible for managing sub-channels. @@ -67,7 +69,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener private Map channels = new HashMap(); private final WebSocketPolicy policy; - private final WebSocketConnection physicalConnection; + private final LogicalConnection physicalConnection; private InetSocketAddress remoteAddress; /** Parsing frames destined for sub-channels */ private MuxParser parser; @@ -76,11 +78,11 @@ public class Muxer implements IncomingFrames, MuxParser.Listener private MuxAddServer addServer; private MuxAddClient addClient; /** The original request headers, used for delta encoded AddChannelRequest blocks */ - private List physicalRequestHeaders; + private UpgradeRequest physicalRequestHeaders; /** The original response headers, used for delta encoded AddChannelResponse blocks */ - private List physicalResponseHeaders; + private UpgradeResponse physicalResponseHeaders; - public Muxer(final WebSocketConnection connection) + public Muxer(final LogicalConnection connection) { this.physicalConnection = connection; this.policy = connection.getPolicy().clonePolicy(); @@ -152,7 +154,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener * Incoming mux encapsulated frames. */ @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { parser.parse(frame); } @@ -383,7 +385,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener /** * Outgoing frame, without mux encapsulated payload. */ - public Future output(long channelId, WebSocketFrame frame) throws IOException + public Future output(long channelId, Frame frame) throws IOException { if (LOG.isDebugEnabled()) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerOutgoingFrameHandler.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerOutgoingFrameHandler.java deleted file mode 100644 index 57508c5815a..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerOutgoingFrameHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.extensions.mux; - -import java.io.IOException; -import java.util.concurrent.Future; - -import javax.net.websocket.SendResult; -import javax.net.websocket.extensions.FrameHandler; - -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; - -/** - * Process frames destined for the network layer. - *

- * Outgoing frames are not mangled by this handler, as they have already been captured by the {@link Muxer} and encapsulated. - */ -public class MuxerOutgoingFrameHandler extends AbstractJettyFrameHandler implements OutgoingFrames -{ - public MuxerOutgoingFrameHandler(FrameHandler nextHandler, Muxer muxer) - { - super(nextHandler); - muxer.setOutgoingFramesHandler(this); - } - - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - // pass through. Muxer already encapsulated frame. - nextJettyHandler(frame); - } - - @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException - { - // TODO Auto-generated method stub - return null; - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddClient.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddClient.java index a572063cbb8..4c524438445 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddClient.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddClient.java @@ -18,8 +18,8 @@ package org.eclipse.jetty.websocket.common.extensions.mux.add; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; /** * Interface for Mux Client to handle receiving a AddChannelResponse diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddServer.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddServer.java index 00f2a7d193d..80bd98ac9f9 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddServer.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxAddServer.java @@ -22,10 +22,10 @@ import java.io.IOException; import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeResponse; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.extensions.mux.MuxChannel; import org.eclipse.jetty.websocket.common.extensions.mux.MuxException; import org.eclipse.jetty.websocket.common.extensions.mux.Muxer; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; /** * Server interface, for dealing with incoming AddChannelRequest / AddChannelResponse flows. diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java index db58910ab58..7111770d799 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java @@ -44,17 +44,19 @@ import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.Generator; +import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.WebSocketSession; /** * Provides the implementation of {@link WebSocketConnection} within the framework of the new {@link Connection} framework of jetty-io */ -public abstract class AbstractWebSocketConnection extends AbstractConnection implements InternalConnection, SuspendToken +public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection { private static final Logger LOG = Log.getLogger(AbstractWebSocketConnection.class); private static final Logger LOG_FRAMES = Log.getLogger("org.eclipse.jetty.websocket.io.Frames"); @@ -91,6 +93,24 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp this.outputClosed = new AtomicBoolean(false); } + @Override + public void assertInputOpen() throws IOException + { + if (isInputClosed()) + { + throw new IOException("Connection input is closed"); + } + } + + @Override + public void assertOutputOpen() throws IOException + { + if (isOutputClosed()) + { + throw new IOException("Connection output is closed"); + } + } + @Override public void close() { @@ -232,6 +252,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp return parser; } + @Override public WebSocketPolicy getPolicy() { return this.policy; @@ -253,6 +274,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp return scheduler; } + @Override public WebSocketSession getSession() { return session; @@ -370,15 +392,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp return true; } - /** - * Enqueue internal frame from {@link OutgoingFrames} stack for eventual write out on the physical connection. - */ @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { if (LOG.isDebugEnabled()) { - LOG.debug("output({})",frame); + LOG.debug("outgoingFrame({})",frame); } Future future = null; @@ -402,7 +421,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp if (isOpen()) { - if (frame.getOpCode() == OpCode.PING) + if (frame.getType().getOpCode() == OpCode.PING) { queue.prepend(bytes); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/ControlFrameBytes.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/ControlFrameBytes.java index 1c9b20cb327..695a76dad10 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/ControlFrameBytes.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/ControlFrameBytes.java @@ -24,9 +24,9 @@ import javax.net.websocket.SendResult; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; public class ControlFrameBytes extends FrameBytes { @@ -34,7 +34,7 @@ public class ControlFrameBytes extends FrameBytes private ByteBuffer buffer; private ByteBuffer origPayload; - public ControlFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) + public ControlFrameBytes(AbstractWebSocketConnection connection, Frame frame) { super(connection,frame); } @@ -47,7 +47,7 @@ public class ControlFrameBytes extends FrameBytes super.completed(context); - if (frame.getOpCode() == OpCode.CLOSE) + if (frame.getType().getOpCode() == OpCode.CLOSE) { CloseInfo close = new CloseInfo(origPayload,false); connection.onCloseHandshake(false,close); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/DataFrameBytes.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/DataFrameBytes.java index 5ccdd143a3e..76df852806b 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/DataFrameBytes.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/DataFrameBytes.java @@ -24,14 +24,14 @@ import javax.net.websocket.SendResult; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class DataFrameBytes extends FrameBytes { private static final Logger LOG = Log.getLogger(DataFrameBytes.class); private ByteBuffer buffer; - public DataFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) + public DataFrameBytes(AbstractWebSocketConnection connection, Frame frame) { super(connection,frame); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameBytes.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameBytes.java index 0bdaaae9e06..94cc2aaff19 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameBytes.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameBytes.java @@ -28,17 +28,17 @@ import org.eclipse.jetty.util.FutureCallback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Scheduler; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; public abstract class FrameBytes extends FutureCallback implements Runnable { private final static Logger LOG = Log.getLogger(FrameBytes.class); protected final AbstractWebSocketConnection connection; - protected final WebSocketFrame frame; + protected final Frame frame; // Task used to timeout the bytes protected volatile Scheduler.Task task; - protected FrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) + protected FrameBytes(AbstractWebSocketConnection connection, Frame frame) { this.connection = connection; this.frame = frame; @@ -63,7 +63,7 @@ public abstract class FrameBytes extends FutureCallback implements R } cancelTask(); connection.complete(this); - frame.notifySendHandler(); + frame.notifySendSuccess(); } @Override @@ -80,7 +80,7 @@ public abstract class FrameBytes extends FutureCallback implements R LOG.warn("failed(" + v + ")",x); } cancelTask(); - frame.notifySendHandler(x); + frame.notifySendFailed(x); } public abstract ByteBuffer getByteBuffer(); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java index ed2f0ceb6ec..50fac6e53ad 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java @@ -8,7 +8,9 @@ import javax.net.websocket.SendResult; 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.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; public class FramePipes { @@ -29,7 +31,7 @@ public class FramePipes } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { try { @@ -52,7 +54,7 @@ public class FramePipes } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { this.incoming.incomingFrame(frame); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/WebSocketSession.java deleted file mode 100644 index 3cffda47803..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/WebSocketSession.java +++ /dev/null @@ -1,295 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-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.common.io; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.concurrent.Future; - -import javax.net.websocket.SendResult; - -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.SuspendToken; -import org.eclipse.jetty.websocket.api.WebSocketConnection; -import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.ConnectionState; -import org.eclipse.jetty.websocket.common.LogicalConnection; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.events.EventDriver; - -public class WebSocketSession implements WebSocketConnection, LogicalConnection, IncomingFrames, OutgoingFrames -{ - private static final Logger LOG = Log.getLogger(WebSocketSession.class); - - /** - * The reference to the logical connection. - *

- * This will be the {@link AbstractWebSocketConnection} on normal websocket use, and be a MuxChannel when MUX is in the picture. - */ - private final LogicalConnection baseConnection; - private final WebSocketPolicy policy; - private final String subprotocol; - private final EventDriver websocket; - private OutgoingFrames outgoing; - - public WebSocketSession(EventDriver websocket, LogicalConnection connection, WebSocketPolicy policy, String subprotocol) - { - super(); - this.websocket = websocket; - this.baseConnection = connection; - this.policy = policy; - this.subprotocol = subprotocol; - } - - @Override - public void close() - { - baseConnection.close(); - } - - @Override - public void close(int statusCode, String reason) - { - baseConnection.close(statusCode,reason); - } - - @Override - public void disconnect() - { - baseConnection.disconnect(); - } - - public IncomingFrames getIncoming() - { - return websocket; - } - - @Override - public InetSocketAddress getLocalAddress() - { - // TODO Auto-generated method stub - return null; - } - - public OutgoingFrames getOutgoing() - { - return outgoing; - } - - @Override - public WebSocketPolicy getPolicy() - { - return policy; - } - - @Override - public InetSocketAddress getRemoteAddress() - { - return baseConnection.getRemoteAddress(); - } - - @Override - public URI getRequestURI() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConnectionState getState() - { - return baseConnection.getState(); - } - - @Override - public String getSubProtocol() - { - return subprotocol; - } - - @Override - public void incomingError(WebSocketException e) - { - if (baseConnection.isInputClosed()) - { - return; // input is closed - } - // pass on incoming to websocket itself - websocket.incomingError(e); - } - - @Override - public void incomingFrame(WebSocketFrame frame) - { - if (baseConnection.isInputClosed()) - { - return; // input is closed - } - // pass on incoming to websocket itself - websocket.incomingFrame(frame); - } - - @Override - public boolean isInputClosed() - { - return baseConnection.isInputClosed(); - } - - @Override - public boolean isOpen() - { - return baseConnection.isOpen(); - } - - @Override - public boolean isOutputClosed() - { - return baseConnection.isOutputClosed(); - } - - @Override - public boolean isReading() - { - return baseConnection.isReading(); - } - - @Override - public void onCloseHandshake(boolean incoming, CloseInfo close) - { - baseConnection.onCloseHandshake(incoming,close); - } - - public void onConnect() - { - LOG.debug("onConnect()"); - websocket.setSession(this); - websocket.onConnect(); - } - - @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException - { - if (LOG.isDebugEnabled()) - { - LOG.debug("output({}) - {}",frame,outgoing); - } - // forward on to chain - return outgoing.outgoingFrame(frame); - } - - /** - * {@inheritDoc} - */ - @Override - public Future ping(byte[] payload) throws IOException - { - // Delegate the application called ping to the OutgoingFrames interface to allow - // extensions to process the frame appropriately. - WebSocketFrame frame = new WebSocketFrame(OpCode.PING).setPayload(payload); - frame.setFin(true); - return outgoingFrame(frame); - } - - public void setOutgoing(OutgoingFrames outgoing) - { - this.outgoing = outgoing; - } - - @Override - public SuspendToken suspend() - { - return baseConnection.suspend(); - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("WebSocketSession[websocket="); - builder.append(websocket); - builder.append(",baseConnection="); - builder.append(baseConnection); - builder.append(",subprotocol="); - builder.append(subprotocol); - builder.append(",outgoing="); - builder.append(outgoing); - builder.append("]"); - return builder.toString(); - } - - @Override - public Future write(byte[] buf, int offset, int len) throws IOException - { - assertBaseConnectionOpen(); - if (LOG.isDebugEnabled()) - { - LOG.debug("write(byte[],{},{})",offset,len); - } - // Delegate the application called write to the OutgoingFrames interface to allow - // extensions to process the frame appropriately. - WebSocketFrame frame = WebSocketFrame.binary().setPayload(buf,offset,len); - frame.setFin(true); - return outgoingFrame(frame); - } - - @Override - public Future write(ByteBuffer buffer) throws IOException - { - assertBaseConnectionOpen(); - if (LOG.isDebugEnabled()) - { - LOG.debug("write({})",BufferUtil.toDetailString(buffer)); - } - // Delegate the application called write to the OutgoingFrames interface to allow - // extensions to process the frame appropriately. - WebSocketFrame frame = WebSocketFrame.binary().setPayload(buffer); - frame.setFin(true); - return outgoingFrame(frame); - } - - @Override - public Future write(String message) throws IOException - { - assertBaseConnectionOpen(); - if (LOG.isDebugEnabled()) - { - LOG.debug("write(message.length:{})",message.length()); - } - // Delegate the application called ping to the OutgoingFrames interface to allow - // extensions to process the frame appropriately. - WebSocketFrame frame = WebSocketFrame.text(message); - frame.setFin(true); - return outgoingFrame(frame); - } - - private void assertBaseConnectionOpen() throws IOException - { - if (baseConnection.isOutputClosed()) - { - throw new IOException("Connection is closed"); - } - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java index 06af5e8e9b1..a90d041c799 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java @@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload; import java.nio.ByteBuffer; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class DeMaskProcessor implements PayloadProcessor { @@ -45,7 +45,7 @@ public class DeMaskProcessor implements PayloadProcessor } @Override - public void reset(WebSocketFrame frame) + public void reset(Frame frame) { this.isMasked = frame.isMasked(); if (isMasked) diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/NoOpValidator.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/NoOpValidator.java index 0d549620408..b060df03b16 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/NoOpValidator.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/NoOpValidator.java @@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload; import java.nio.ByteBuffer; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * payload validator does no validation. @@ -36,7 +36,7 @@ public class NoOpValidator implements PayloadProcessor } @Override - public void reset(WebSocketFrame frame) + public void reset(Frame frame) { /* do nothing */ } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/PayloadProcessor.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/PayloadProcessor.java index b8aee5be886..271752b6b33 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/PayloadProcessor.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/PayloadProcessor.java @@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.common.io.payload; import java.nio.ByteBuffer; import org.eclipse.jetty.websocket.api.BadPayloadException; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * Process the payload (for demasking, validating, etc..) @@ -38,5 +38,5 @@ public interface PayloadProcessor */ public void process(ByteBuffer payload); - public void reset(WebSocketFrame frame); + public void reset(Frame frame); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/UTF8Validator.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/UTF8Validator.java index c60e130ffea..b85435c251f 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/UTF8Validator.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/UTF8Validator.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.util.Utf8Appendable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BadPayloadException; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * Used to perform validation of UTF8 payload contents (for fast-fail reasons) @@ -104,7 +104,7 @@ public class UTF8Validator extends Utf8Appendable implements PayloadProcessor } @Override - public void reset(WebSocketFrame frame) + public void reset(Frame frame) { /* do nothing */ } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/InternalConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageOutputStream.java similarity index 54% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/InternalConnection.java rename to jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageOutputStream.java index e03d1839dbf..7276bb4fc00 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/InternalConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageOutputStream.java @@ -16,19 +16,34 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.io; +package org.eclipse.jetty.websocket.common.message; -import java.util.List; +import java.io.IOException; +import java.io.OutputStream; -import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.LogicalConnection; -public interface InternalConnection extends LogicalConnection +public class MessageOutputStream extends OutputStream { - // TODO: find way to remove - void configureFromExtensions(List extensions); + private final LogicalConnection connection; + private final OutgoingFrames outgoing; - void setIncoming(IncomingFrames incoming); + public MessageOutputStream(LogicalConnection connection, OutgoingFrames outgoing) + { + this.connection = connection; + this.outgoing = outgoing; + } - void setSession(WebSocketSession session); + public boolean isClosed() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public void write(int b) throws IOException + { + // TODO Auto-generated method stub + } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java new file mode 100644 index 00000000000..99b7195b927 --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java @@ -0,0 +1,65 @@ +// +// ======================================================================== +// Copyright (c) 1995-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.common.message; + +import java.io.IOException; +import java.io.Writer; + +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.LogicalConnection; + +public class MessageWriter extends Writer +{ + private final LogicalConnection connection; + private final OutgoingFrames outgoing; + + public MessageWriter(LogicalConnection connection, OutgoingFrames outgoing) + { + this.connection = connection; + this.outgoing = outgoing; + } + + @Override + public void close() throws IOException + { + // TODO Auto-generated method stub + + } + + @Override + public void flush() throws IOException + { + // TODO Auto-generated method stub + + } + + public boolean isClosed() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException + { + // TODO Auto-generated method stub + + } + +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerIncomingFrameHandler.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FinishedFuture.java similarity index 52% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerIncomingFrameHandler.java rename to jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FinishedFuture.java index be50dbee92b..a18178241dd 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxerIncomingFrameHandler.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FinishedFuture.java @@ -16,30 +16,37 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.extensions.mux; +package org.eclipse.jetty.websocket.common; -import javax.net.websocket.extensions.FrameHandler; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; +import javax.net.websocket.SendResult; -/** - * Process incoming frames and forward them off to the Muxer. - */ -public class MuxerIncomingFrameHandler extends AbstractJettyFrameHandler +public class FinishedFuture extends FutureTask implements Future { - private final IncomingFrames muxerHandler; + public static Future INSTANCE; - public MuxerIncomingFrameHandler(FrameHandler nextHandler, Muxer muxer) + static { - super(nextHandler); - this.muxerHandler = muxer; + Callable callable = new Callable() + { + @Override + public SendResult call() throws Exception + { + return new SendResult(); + } + }; + + FinishedFuture fut = new FinishedFuture(callable); + fut.run(); + + INSTANCE = fut; } - @Override - public void handleJettyFrame(WebSocketFrame frame) + public FinishedFuture(Callable callable) { - this.muxerHandler.incomingFrame(frame); + super(callable); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/IncomingFramesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/IncomingFramesCapture.java index bc26755e275..8a2cfd37077 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/IncomingFramesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/IncomingFramesCapture.java @@ -26,24 +26,17 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.junit.Assert; -public class IncomingFramesCapture extends AbstractJettyFrameHandler implements IncomingFrames +public class IncomingFramesCapture implements IncomingFrames { private static final Logger LOG = Log.getLogger(IncomingFramesCapture.class); private LinkedList frames = new LinkedList<>(); private LinkedList errors = new LinkedList<>(); - public IncomingFramesCapture() - { - super(null); // End of Chain (don't pass frames to anyone else) - } - public void assertErrorCount(int expectedCount) { Assert.assertThat("Captured error count",errors.size(),is(expectedCount)); @@ -84,7 +77,7 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements System.err.printf("Captured %d incoming frames%n",frames.size()); for (int i = 0; i < frames.size(); i++) { - WebSocketFrame frame = frames.get(i); + Frame frame = frames.get(i); System.err.printf("[%3d] %s%n",i,frame); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); } @@ -126,12 +119,6 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements return frames; } - @Override - public void handleJettyFrame(WebSocketFrame frame) - { - incomingFrame(frame); - } - @Override public void incomingError(WebSocketException e) { @@ -140,7 +127,7 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { WebSocketFrame copy = new WebSocketFrame(frame); frames.add(copy); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingFramesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingFramesCapture.java index d761a7c4ff7..c2885e491bf 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingFramesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingFramesCapture.java @@ -26,19 +26,14 @@ import java.util.concurrent.Future; import javax.net.websocket.SendResult; import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.junit.Assert; -public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements OutgoingFrames +public class OutgoingFramesCapture implements OutgoingFrames { private LinkedList frames = new LinkedList<>(); - public OutgoingFramesCapture() - { - super(null); // Do not forward frames anywhere else, capture is the end of the line - } - public void assertFrameCount(int expectedCount) { Assert.assertThat("Captured frame count",frames.size(),is(expectedCount)); @@ -64,7 +59,7 @@ public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements System.out.printf("Captured %d outgoing writes%n",frames.size()); for (int i = 0; i < frames.size(); i++) { - WebSocketFrame frame = frames.get(i); + Frame frame = frames.get(i); System.out.printf("[%3d] %s%n",i,frame); System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); } @@ -89,16 +84,11 @@ public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements } @Override - public void handleJettyFrame(WebSocketFrame frame) + public Future outgoingFrame(Frame frame) { - outgoingFrame(frame); - } + WebSocketFrame copy = new WebSocketFrame(frame); + frames.add(copy); - @Override - public Future outgoingFrame(WebSocketFrame frame) - { - frames.add(frame); - - return null; // FIXME: should return completed future. + return FinishedFuture.INSTANCE; } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingNetworkBytesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingNetworkBytesCapture.java index c9c54d08780..2826a8f959d 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingNetworkBytesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingNetworkBytesCapture.java @@ -30,21 +30,20 @@ import javax.net.websocket.SendResult; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.TypeUtil; -import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.junit.Assert; /** * Capture outgoing network bytes. */ -public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler implements OutgoingFrames +public class OutgoingNetworkBytesCapture implements OutgoingFrames { private final Generator generator; private List captured; public OutgoingNetworkBytesCapture(Generator generator) { - super(null); // no sub handling, capture is end of the line. this.generator = generator; this.captured = new ArrayList<>(); } @@ -63,24 +62,11 @@ public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler imple } @Override - public void handleJettyFrame(WebSocketFrame frame) - { - try - { - outgoingFrame(frame); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { ByteBuffer buf = generator.generate(frame); captured.add(buf.slice()); - return null; // FIXME: should return completed future. + return FinishedFuture.INSTANCE; } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java index 9ce4bfb3add..5acc158904a 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; @@ -146,7 +147,7 @@ public class RFC6455ExamplesParserTest capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame bin = capture.getFrames().get(0); + Frame bin = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); @@ -186,7 +187,7 @@ public class RFC6455ExamplesParserTest capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame bin = capture.getFrames().get(0); + Frame bin = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); ByteBuffer data = bin.getPayload(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/UnitGenerator.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/UnitGenerator.java index d4e29819fd0..1bf8908f36d 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/UnitGenerator.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/UnitGenerator.java @@ -24,8 +24,7 @@ import java.util.List; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.Generator; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * Convenience Generator. @@ -34,7 +33,7 @@ public class UnitGenerator extends Generator { public static ByteBuffer generate(List frames) { - // Create non-symmetrical mask (shows mask bytes order issues) + // Create non-symmetrical mask (helps show mask bytes order issues) byte[] MASK = { 0x11, 0x22, 0x33, 0x44 }; @@ -43,7 +42,7 @@ public class UnitGenerator extends Generator // Generate into single bytebuffer int buflen = 0; - for (WebSocketFrame f : frames) + for (Frame f : frames) { buflen += f.getPayloadLength() + Generator.OVERHEAD; } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java index 6a102840321..36bb5f5687e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java @@ -22,6 +22,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; @@ -320,7 +321,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -354,7 +355,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -388,7 +389,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -422,7 +423,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -461,7 +462,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -498,7 +499,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); } @@ -522,7 +523,7 @@ public class TestABCase1_1 capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0)); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java index 659069acde3..4c476f502f4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; @@ -336,7 +337,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -370,7 +371,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -404,7 +405,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -438,7 +439,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -473,7 +474,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -510,7 +511,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); } @@ -534,7 +535,7 @@ public class TestABCase1_2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.BINARY,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0)); // Assert.assertNull("BinaryFrame.payload",pActual.getPayloadData()); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java index cdc03e50186..49aaca4a6fc 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException; 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.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; @@ -201,7 +202,7 @@ public class TestABCase2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); } @@ -231,7 +232,7 @@ public class TestABCase2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); } @@ -254,7 +255,7 @@ public class TestABCase2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(0)); Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength()); } @@ -285,7 +286,7 @@ public class TestABCase2 capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(message.length())); Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength()); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java index ae59078e5d1..31c8b3a3bca 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java @@ -26,6 +26,7 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; @@ -80,7 +81,7 @@ public class TestABCase7_3 capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0)); } @@ -154,7 +155,7 @@ public class TestABCase7_3 capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2)); } @@ -212,7 +213,7 @@ public class TestABCase7_3 capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2)); } @@ -282,7 +283,7 @@ public class TestABCase7_3 capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); - WebSocketFrame pActual = capture.getFrames().get(0); + Frame pActual = capture.getFrames().get(0); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125)); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java index 7a7feb6b2be..7d5c643b6ce 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.events; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; @@ -39,7 +40,7 @@ public class EventDriverTest @Rule public TestName testname = new TestName(); - private WebSocketFrame makeBinaryFrame(String content, boolean fin) + private Frame makeBinaryFrame(String content, boolean fin) { return WebSocketFrame.binary().setFin(fin).setPayload(content); } @@ -50,9 +51,8 @@ public class EventDriverTest AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket(); EventDriver driver = wrap(socket); - LocalWebSocketSession conn = new LocalWebSocketSession(testname); - driver.setSession(conn); - driver.onConnect(); + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); socket.capture.assertEventCount(2); @@ -66,9 +66,8 @@ public class EventDriverTest AnnotatedBinaryArraySocket socket = new AnnotatedBinaryArraySocket(); EventDriver driver = wrap(socket); - LocalWebSocketSession conn = new LocalWebSocketSession(testname); - driver.setSession(conn); - driver.onConnect(); + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); @@ -84,9 +83,8 @@ public class EventDriverTest AnnotatedFramesSocket socket = new AnnotatedFramesSocket(); EventDriver driver = wrap(socket); - LocalWebSocketSession conn = new LocalWebSocketSession(testname); - driver.setSession(conn); - driver.onConnect(); + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); driver.incomingFrame(new WebSocketFrame(OpCode.PING).setPayload("PING")); driver.incomingFrame(WebSocketFrame.text("Text Me")); driver.incomingFrame(WebSocketFrame.binary().setPayload("Hello Bin")); @@ -107,9 +105,8 @@ public class EventDriverTest AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket(); EventDriver driver = wrap(socket); - LocalWebSocketSession conn = new LocalWebSocketSession(testname); - driver.setSession(conn); - driver.onConnect(); + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); @@ -125,9 +122,8 @@ public class EventDriverTest ListenerBasicSocket socket = new ListenerBasicSocket(); EventDriver driver = wrap(socket); - LocalWebSocketSession conn = new LocalWebSocketSession(testname); - driver.setSession(conn); - driver.onConnect(); + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); driver.incomingFrame(WebSocketFrame.text("Hello World")); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java index 4366b7f6498..640ce4084de 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java @@ -26,13 +26,12 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import javax.net.websocket.extensions.FrameHandler; - import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.OpCode; @@ -58,7 +57,7 @@ public class FragmentExtensionTest ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ext.setConfig(config); - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); // Quote List quote = new ArrayList<>(); @@ -69,8 +68,8 @@ public class FragmentExtensionTest // Manually create frame and pass into extension for (String q : quote) { - WebSocketFrame frame = WebSocketFrame.text(q); - incomingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text(q); + ext.incomingFrame(frame); } int len = quote.size(); @@ -110,11 +109,11 @@ public class FragmentExtensionTest ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ext.setConfig(config); - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); String payload = "Are you there?"; - WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); - incomingHandler.handleFrame(ping); + Frame ping = WebSocketFrame.ping().setPayload(payload); + ext.incomingFrame(ping); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING,1); @@ -145,7 +144,7 @@ public class FragmentExtensionTest ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=20"); ext.setConfig(config); - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); // Quote List quote = new ArrayList<>(); @@ -156,8 +155,8 @@ public class FragmentExtensionTest // Write quote as separate frames for (String section : quote) { - WebSocketFrame frame = WebSocketFrame.text(section); - outgoingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text(section); + ext.outgoingFrame(frame); } // Expected Frames @@ -214,7 +213,7 @@ public class FragmentExtensionTest ExtensionConfig config = ExtensionConfig.parse("fragment"); ext.setConfig(config); - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); // Quote List quote = new ArrayList<>(); @@ -225,8 +224,8 @@ public class FragmentExtensionTest // Write quote as separate frames for (String section : quote) { - WebSocketFrame frame = WebSocketFrame.text(section); - outgoingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text(section); + ext.outgoingFrame(frame); } // Expected Frames @@ -278,12 +277,12 @@ public class FragmentExtensionTest ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ext.setConfig(config); - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); String payload = "Are you there?"; - WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); + Frame ping = WebSocketFrame.ping().setPayload(payload); - outgoingHandler.handleFrame(ping); + ext.outgoingFrame(ping); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING,1); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java index 9ad26c88160..3ba2433f45e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java @@ -23,11 +23,10 @@ import static org.hamcrest.Matchers.*; import java.io.IOException; import java.nio.ByteBuffer; -import javax.net.websocket.extensions.FrameHandler; - import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.OpCode; @@ -48,10 +47,10 @@ public class IdentityExtensionTest IncomingFramesCapture capture = new IncomingFramesCapture(); Extension ext = new IdentityExtension(); - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); - WebSocketFrame frame = WebSocketFrame.text("hello"); - incomingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text("hello"); + ext.incomingFrame(frame); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.TEXT,1); @@ -77,10 +76,10 @@ public class IdentityExtensionTest OutgoingFramesCapture capture = new OutgoingFramesCapture(); Extension ext = new IdentityExtension(); - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); - WebSocketFrame frame = WebSocketFrame.text("hello"); - outgoingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text("hello"); + ext.outgoingFrame(frame); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.TEXT,1); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtensionTest.java index a5b58d55195..be08b18b742 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageCompressionExtensionTest.java @@ -26,14 +26,13 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import javax.net.websocket.extensions.FrameHandler; - import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.OpCode; @@ -49,7 +48,7 @@ public class PerMessageCompressionExtensionTest WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); // Setup extension - PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); + MessageCompressionExtension ext = new MessageCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(policy); ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); @@ -59,7 +58,7 @@ public class PerMessageCompressionExtensionTest IncomingFramesCapture capture = new IncomingFramesCapture(); // Wire up stack - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); // Receive frame String hex = hexStr.replaceAll("\\s*0x",""); @@ -69,7 +68,7 @@ public class PerMessageCompressionExtensionTest frame.setPayload(net); // Send frame into stack - incomingHandler.handleFrame(frame); + ext.incomingFrame(frame); // Verify captured frames. capture.assertFrameCount(1); @@ -162,7 +161,7 @@ public class PerMessageCompressionExtensionTest */ @Test public void testIncomingPing() { - PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); + MessageCompressionExtension ext = new MessageCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(WebSocketPolicy.newServerPolicy()); ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); @@ -172,11 +171,11 @@ public class PerMessageCompressionExtensionTest IncomingFramesCapture capture = new IncomingFramesCapture(); // Wire up stack - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); String payload = "Are you there?"; - WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); - incomingHandler.handleFrame(ping); + Frame ping = WebSocketFrame.ping().setPayload(payload); + ext.incomingFrame(ping); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING,1); @@ -199,7 +198,7 @@ public class PerMessageCompressionExtensionTest @Test public void testIncomingUncompressedFrames() { - PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); + MessageCompressionExtension ext = new MessageCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(WebSocketPolicy.newServerPolicy()); ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); @@ -209,7 +208,8 @@ public class PerMessageCompressionExtensionTest IncomingFramesCapture capture = new IncomingFramesCapture(); // Wire up stack - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); + ext.setNextIncomingFrames(capture); + // Quote List quote = new ArrayList<>(); quote.add("No amount of experimentation can ever prove me right;"); @@ -222,7 +222,7 @@ public class PerMessageCompressionExtensionTest WebSocketFrame frame = new WebSocketFrame(OpCode.TEXT); frame.setPayload(q); frame.setRsv1(false); // indication to extension that frame is not compressed (ie: a normal frame) - incomingHandler.handleFrame(frame); + ext.incomingFrame(frame); } int len = quote.size(); @@ -254,7 +254,7 @@ public class PerMessageCompressionExtensionTest @Test public void testOutgoingFrames() throws IOException { - PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); + MessageCompressionExtension ext = new MessageCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(WebSocketPolicy.newServerPolicy()); ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); @@ -264,7 +264,7 @@ public class PerMessageCompressionExtensionTest OutgoingFramesCapture capture = new OutgoingFramesCapture(); // Wire up stack - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); // Quote List quote = new ArrayList<>(); @@ -275,8 +275,8 @@ public class PerMessageCompressionExtensionTest // Write quote as separate frames for (String section : quote) { - WebSocketFrame frame = WebSocketFrame.text(section); - outgoingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text(section); + ext.outgoingFrame(frame); } int len = quote.size(); @@ -314,7 +314,7 @@ public class PerMessageCompressionExtensionTest @Test public void testOutgoingPing() throws IOException { - PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); + MessageCompressionExtension ext = new MessageCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(WebSocketPolicy.newServerPolicy()); ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); @@ -324,12 +324,12 @@ public class PerMessageCompressionExtensionTest OutgoingFramesCapture capture = new OutgoingFramesCapture(); // Wire up stack - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); String payload = "Are you there?"; - WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); + Frame ping = WebSocketFrame.ping().setPayload(payload); - outgoingHandler.handleFrame(ping); + ext.outgoingFrame(ping); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING,1); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtensionTest.java index b04fd8a5e9e..97bd530aa72 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/WebkitDeflateFrameExtensionTest.java @@ -26,8 +26,6 @@ import java.util.Collections; import java.util.zip.Deflater; import java.util.zip.Inflater; -import javax.net.websocket.extensions.FrameHandler; - import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; @@ -35,6 +33,7 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; @@ -42,8 +41,6 @@ import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OutgoingNetworkBytesCapture; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.IncomingFrameHandler; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; import org.junit.Assert; import org.junit.Test; @@ -53,7 +50,7 @@ public class WebkitDeflateFrameExtensionTest { WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension(); + FrameCompressionExtension ext = new FrameCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(policy); @@ -64,12 +61,11 @@ public class WebkitDeflateFrameExtensionTest IncomingFramesCapture capture = new IncomingFramesCapture(); // Wire up stack - FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); - IncomingFrames incoming = new IncomingFrameHandler(incomingHandler); + ext.setNextIncomingFrames(capture); Parser parser = new Parser(policy); parser.configureFromExtensions(Collections.singletonList(ext)); - parser.setIncomingFramesHandler(incoming); + parser.setIncomingFramesHandler(ext); parser.parse(ByteBuffer.wrap(raw)); @@ -97,7 +93,7 @@ public class WebkitDeflateFrameExtensionTest { WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension(); + FrameCompressionExtension ext = new FrameCompressionExtension(); ext.setBufferPool(new MappedByteBufferPool()); ext.setPolicy(policy); @@ -110,10 +106,10 @@ public class WebkitDeflateFrameExtensionTest generator.configureFromExtensions(Collections.singletonList(ext)); OutgoingNetworkBytesCapture capture = new OutgoingNetworkBytesCapture(generator); - FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); + ext.setNextOutgoingFrames(capture); - WebSocketFrame frame = WebSocketFrame.text(text); - outgoingHandler.handleFrame(frame); + Frame frame = WebSocketFrame.text(text); + ext.outgoingFrame(frame); capture.assertBytes(0,expectedHex); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxDecoder.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxDecoder.java index 6730fb29e16..5535f4e8cfe 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxDecoder.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxDecoder.java @@ -23,8 +23,8 @@ import java.util.concurrent.Future; import javax.net.websocket.SendResult; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; /** * Helpful utility class to parse arbitrary mux events from a physical connection's OutgoingFrames. @@ -42,7 +42,7 @@ public class MuxDecoder extends MuxEventCapture implements OutgoingFrames } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { parser.parse(frame); return null; // FIXME: should return completed future. diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxEncoder.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxEncoder.java index 0d2fc9e1af4..66847ba21f7 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxEncoder.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxEncoder.java @@ -20,12 +20,12 @@ package org.eclipse.jetty.websocket.common.extensions.mux; import java.io.IOException; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.mux.MuxControlBlock; import org.eclipse.jetty.websocket.common.extensions.mux.MuxGenerator; import org.eclipse.jetty.websocket.common.io.FramePipes; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; /** * Helpful utility class to send arbitrary mux events into a physical connection's IncomingFrames. diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParserRFCTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParserRFCTest.java index c3a9d1ec402..b902fbadb28 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParserRFCTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/MuxParserRFCTest.java @@ -32,6 +32,7 @@ import java.util.regex.Pattern; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; @@ -81,7 +82,7 @@ public class MuxParserRFCTest MuxParser parser = new MuxParser(); MuxEventCapture capture = new MuxEventCapture(); parser.setEvents(capture); - for(WebSocketFrame frame: frames) { + for(Frame frame: frames) { parser.parse(frame); } return capture; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddClient.java index 4f1cc8232d6..f27963a2239 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddClient.java @@ -18,9 +18,8 @@ package org.eclipse.jetty.websocket.common.extensions.mux.add; -import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; public class DummyMuxAddClient implements MuxAddClient { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddServer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddServer.java index cbe55a75712..85bd1186e21 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddServer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/DummyMuxAddServer.java @@ -25,14 +25,13 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriverFactory; import org.eclipse.jetty.websocket.common.extensions.mux.MuxChannel; import org.eclipse.jetty.websocket.common.extensions.mux.MuxException; import org.eclipse.jetty.websocket.common.extensions.mux.Muxer; -import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; import examples.echo.AdapterEchoSocket; @@ -79,11 +78,12 @@ public class DummyMuxAddServer implements MuxAddServer response.append("\r\n"); EventDriver websocket = this.eventDriverFactory.wrap(echo); - WebSocketSession session = new WebSocketSession(websocket,channel,channel.getPolicy(),"echo"); + WebSocketSession session = new WebSocketSession(request.getRequestURI(),websocket,channel); + session.setNegotiatedSubprotocol("echo"); channel.setSession(session); channel.setSubProtocol("echo"); channel.onOpen(); - session.onConnect(); + session.open(); MuxAddChannelResponse addChannelResponse = new MuxAddChannelResponse(); addChannelResponse.setChannelId(channel.getChannelId()); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxerAddServerTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxerAddServerTest.java index 7106dd67d5e..8f86234150b 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxerAddServerTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/mux/add/MuxerAddServerTest.java @@ -60,7 +60,7 @@ public class MuxerAddServerTest muxer.setOutgoingFramesHandler(clientRead); // Wire up physical connection to forward incoming frames to muxer - physical.setIncoming(muxer); + physical.setNextIncomingFrames(muxer); // Client simulator // Can inject mux encapsulated frames into physical connection as if from diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java index 23cff7fba1a..32ec59254e3 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java @@ -30,10 +30,12 @@ import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.LogicalConnection; -import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.junit.rules.TestName; public class LocalWebSocketConnection implements WebSocketConnection, LogicalConnection, IncomingFrames @@ -58,6 +60,16 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon this.id = testname.getMethodName(); } + @Override + public void assertInputOpen() throws IOException + { + } + + @Override + public void assertOutputOpen() throws IOException + { + } + @Override public void close() { @@ -105,6 +117,12 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon return null; } + @Override + public WebSocketSession getSession() + { + return null; + } + @Override public ConnectionState getState() { @@ -124,7 +142,7 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { incoming.incomingFrame(frame); } @@ -163,18 +181,23 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { return null; } @Override - public Future ping(byte[] payload) throws IOException + public void ping(ByteBuffer buf) throws IOException { - return null; } - public void setIncoming(IncomingFrames incoming) + @Override + public void resume() + { + } + + @Override + public void setNextIncomingFrames(IncomingFrames incoming) { this.incoming = incoming; } @@ -184,6 +207,11 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon this.policy = policy; } + @Override + public void setSession(WebSocketSession session) + { + } + @Override public SuspendToken suspend() { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketSession.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketSession.java index 1af0022ae10..52cdd245062 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketSession.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketSession.java @@ -18,10 +18,11 @@ package org.eclipse.jetty.websocket.common.io; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import java.net.URI; + import org.eclipse.jetty.websocket.common.OutgoingFramesCapture; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; import org.junit.rules.TestName; public class LocalWebSocketSession extends WebSocketSession @@ -29,17 +30,12 @@ public class LocalWebSocketSession extends WebSocketSession private String id; private OutgoingFramesCapture outgoingCapture; - public LocalWebSocketSession(TestName testname) - { - this(testname,null); - outgoingCapture = new OutgoingFramesCapture(); - setOutgoing(outgoingCapture); - } - public LocalWebSocketSession(TestName testname, EventDriver driver) { - super(driver,new LocalWebSocketConnection(testname),WebSocketPolicy.newServerPolicy(),"testing"); + super(URI.create("ws://localhost/LocalWebSocketSesssion/" + testname.getMethodName()),driver,new LocalWebSocketConnection(testname)); this.id = testname.getMethodName(); + outgoingCapture = new OutgoingFramesCapture(); + setOutgoingHandler(outgoingCapture); } public OutgoingFramesCapture getOutgoingCapture() diff --git a/jetty-websocket/websocket-server/pom.xml b/jetty-websocket/websocket-server/pom.xml index 2912aa642dd..7efca1e06d3 100644 --- a/jetty-websocket/websocket-server/pom.xml +++ b/jetty-websocket/websocket-server/pom.xml @@ -17,17 +17,7 @@ org.eclipse.jetty.websocket - websocket-api - ${project.version} - - - org.eclipse.jetty.websocket - websocket-common - ${project.version} - - - org.eclipse.jetty.websocket - websocket-servlet + websocket-client ${project.version} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/PassthruFrameHandler.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/JettyServerContainer.java similarity index 63% rename from jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/PassthruFrameHandler.java rename to jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/JettyServerContainer.java index 3bfedc13d9e..43a12545653 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/PassthruFrameHandler.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/JettyServerContainer.java @@ -16,17 +16,19 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.extensions; +package org.eclipse.jetty.websocket.server; -import javax.net.websocket.extensions.FrameHandler; +import javax.net.websocket.Endpoint; +import javax.net.websocket.ServerContainer; +import javax.net.websocket.ServerEndpointConfiguration; -/** - * FrameHandler that just passes frames through with no modification. - */ -public class PassthruFrameHandler extends FrameHandler +import org.eclipse.jetty.websocket.client.JettyClientContainer; + +public class JettyServerContainer extends JettyClientContainer implements ServerContainer { - public PassthruFrameHandler(FrameHandler nextHandler) + @Override + public void publishServer(Endpoint endpoint, ServerEndpointConfiguration ilc) { - super(nextHandler); + // TODO Auto-generated method stub } } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java index f3bae1e7605..68f0b2ae965 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java @@ -21,20 +21,19 @@ package org.eclipse.jetty.websocket.server; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.websocket.api.UpgradeRequest; -import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.util.QuoteUtil; public class ServletWebSocketRequest extends UpgradeRequest { - private List extensions; private Map cookieMap; private HttpServletRequest req; @@ -43,12 +42,32 @@ public class ServletWebSocketRequest extends UpgradeRequest super(request.getRequestURI()); this.req = request; + // Copy Request Line Details + setMethod(request.getMethod()); + setHttpVersion(request.getProtocol()); + + // Copy Cookies cookieMap = new HashMap(); for (Cookie cookie : request.getCookies()) { cookieMap.put(cookie.getName(),cookie.getValue()); } + // Copy Headers + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) + { + String name = headerNames.nextElement(); + Enumeration valuesEnum = request.getHeaders(name); + List values = new ArrayList<>(); + while (valuesEnum.hasMoreElements()) + { + values.add(valuesEnum.nextElement()); + } + setHeader(name,values); + } + + // Parse Sub Protocols Enumeration protocols = request.getHeaders("Sec-WebSocket-Protocol"); List subProtocols = new ArrayList<>(); String protocol = null; @@ -62,14 +81,15 @@ public class ServletWebSocketRequest extends UpgradeRequest } setSubProtocols(subProtocols); - extensions = new ArrayList<>(); + // Parse Extension Configurations Enumeration e = request.getHeaders("Sec-WebSocket-Extensions"); while (e.hasMoreElements()) { - QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),","); - while (tok.hasMoreTokens()) + Iterator extTokenIter = QuoteUtil.splitAt(e.nextElement(),","); + while (extTokenIter.hasNext()) { - ExtensionConfig config = ExtensionConfig.parse(tok.nextToken()); + String extToken = extTokenIter.next(); + ExtensionConfig config = ExtensionConfig.parse(extToken); addExtensions(config); } } @@ -98,21 +118,4 @@ public class ServletWebSocketRequest extends UpgradeRequest { this.req.setAttribute(name,o); } - - public void setValidExtensions(List valid) - { - if (this.extensions != null) - { - this.extensions.clear(); - } - else - { - this.extensions = new ArrayList<>(); - } - - for (Extension ext : valid) - { - extensions.add(ext.getConfig()); - } - } } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java index d4f5c6321be..b4cf57af0c8 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java @@ -32,19 +32,24 @@ public class ServletWebSocketResponse extends UpgradeResponse { super(); this.resp = resp; - // TODO: copy values from resp + } + + @Override + public void addHeader(String name, String value) + { + this.resp.addHeader(name,value); } @Override public int getStatusCode() { - throw new UnsupportedOperationException("Server cannot get Status Code"); + return this.resp.getStatus(); } @Override public String getStatusReason() { - throw new UnsupportedOperationException("Server cannot get Status Reason"); + throw new UnsupportedOperationException("Server cannot get Status Reason Message"); } public boolean isCommitted() @@ -65,6 +70,12 @@ public class ServletWebSocketResponse extends UpgradeResponse resp.sendError(HttpServletResponse.SC_FORBIDDEN,message); } + @Override + public void setHeader(String name, String value) + { + this.resp.setHeader(name,value); + } + public void setStatus(int status) { this.resp.setStatus(status); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/UpgradeContext.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/UpgradeContext.java index 43bb3415060..360eda8f625 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/UpgradeContext.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/UpgradeContext.java @@ -20,15 +20,15 @@ package org.eclipse.jetty.websocket.server; import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeResponse; -import org.eclipse.jetty.websocket.common.io.InternalConnection; +import org.eclipse.jetty.websocket.common.LogicalConnection; public class UpgradeContext { - private InternalConnection connection; + private LogicalConnection connection; private UpgradeRequest request; private UpgradeResponse response; - public InternalConnection getConnection() + public LogicalConnection getConnection() { return connection; } @@ -43,7 +43,7 @@ public class UpgradeContext return response; } - public void setConnection(InternalConnection connection) + public void setConnection(LogicalConnection connection) { this.connection = connection; } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java index 8f4a821fe17..09d857544ff 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java @@ -18,16 +18,15 @@ package org.eclipse.jetty.websocket.server; -import java.util.List; +import java.net.InetSocketAddress; import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Extension; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; public class WebSocketServerConnection extends AbstractWebSocketConnection { @@ -43,10 +42,15 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection } @Override - public void configureFromExtensions(List extensions) + public InetSocketAddress getLocalAddress() { - getParser().configureFromExtensions(extensions); - getGenerator().configureFromExtensions(extensions); + return getEndPoint().getLocalAddress(); + } + + @Override + public InetSocketAddress getRemoteAddress() + { + return getEndPoint().getRemoteAddress(); } @Override @@ -68,7 +72,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection } @Override - public void setIncoming(IncomingFrames incoming) + public void setNextIncomingFrames(IncomingFrames incoming) { getParser().setIncomingFramesHandler(incoming); } 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 e9a3ae6e9ec..f53ce4597b2 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 @@ -46,16 +46,14 @@ import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.annotations.WebSocket; -import org.eclipse.jetty.websocket.api.extensions.Extension; -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.LogicalConnection; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriverFactory; -import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.InternalConnection; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; -import org.eclipse.jetty.websocket.common.io.WebSocketSession; +import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455; /** @@ -90,7 +88,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc private final String supportedVersions; private final WebSocketPolicy basePolicy; private final EventDriverFactory eventDriverFactory; - private final WebSocketExtensionRegistry extensionRegistry; + private final WebSocketExtensionFactory extensionFactory; private WebSocketCreator creator; private List> registeredSocketClasses; @@ -108,7 +106,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc this.basePolicy = policy; this.eventDriverFactory = new EventDriverFactory(basePolicy); - this.extensionRegistry = new WebSocketExtensionRegistry(basePolicy,bufferPool); + this.extensionFactory = new WebSocketExtensionFactory(basePolicy,bufferPool); this.creator = this; // Create supportedVersions @@ -166,11 +164,18 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc return upgrade(sockreq,sockresp,driver); } - protected void closeConnections() + protected void closeAllConnections() { for (WebSocketSession session : sessions) { - session.close(); + try + { + session.close(); + } + catch (IOException e) + { + LOG.warn("CloseAllConnections Close failure",e); + } } sessions.clear(); } @@ -205,7 +210,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc @Override protected void doStop() throws Exception { - closeConnections(); + closeAllConnections(); super.doStop(); } @@ -214,9 +219,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc return this.creator; } - public ExtensionFactory getExtensionRegistry() + public ExtensionFactory getExtensionFactory() { - return extensionRegistry; + return extensionFactory; } /** @@ -231,26 +236,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc return basePolicy; } - public List initExtensions(List requested) - { - List extensions = new ArrayList(); - - for (ExtensionConfig cfg : requested) - { - Extension extension = extensionRegistry.newInstance(cfg); - - if (extension == null) - { - continue; - } - - LOG.debug("added {}",extension); - extensions.add(extension); - } - LOG.debug("extensions={}",extensions); - return extensions; - } - public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response) { String upgrade = request.getHeader("Upgrade"); @@ -324,7 +309,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc return false; } boolean ret = sessions.offer(session); - session.onConnect(); + session.open(); return ret; } @@ -379,7 +364,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc // Create connection UpgradeContext context = getActiveUpgradeContext(); - InternalConnection connection = context.getConnection(); + LogicalConnection connection = context.getConnection(); if (connection == null) { @@ -394,46 +379,26 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc } // Initialize / Negotiate Extensions - WebSocketSession session = new WebSocketSession(driver,connection,getPolicy(),response.getAcceptedSubProtocol()); + WebSocketSession session = new WebSocketSession(request.getRequestURI(),driver,connection); + session.setPolicy(getPolicy().clonePolicy()); + session.setNegotiatedSubprotocol(response.getAcceptedSubProtocol()); + session.setNegotiatedExtensionConfigs(request.getExtensions()); + session.setExtensionFactory(extensionFactory); connection.setSession(session); - List extensions = initExtensions(request.getExtensions()); - request.setValidExtensions(extensions); // Start with default routing. IncomingFrames incoming = session; OutgoingFrames outgoing = connection; - // Connect extensions - if (extensions != null) - { - connection.configureFromExtensions(extensions); - - // FIXME: - // Iterator extIter; - // // Connect outgoings - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // Extension ext = extIter.next(); - // ext.setNextOutgoingFrames(outgoing); - // outgoing = ext; - // } - // - // // Connect incomings - // Collections.reverse(extensions); - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // Extension ext = extIter.next(); - // ext.setNextIncomingFrames(incoming); - // incoming = ext; - // } - } + // if (extensions != null) + // { + // // FIXME connection.configureFromExtensions(extensions); + // } // configure session for outgoing flows - session.setOutgoing(outgoing); + session.setOutgoingHandler(outgoing); // configure connection for incoming flows - connection.setIncoming(incoming); + connection.setNextIncomingFrames(incoming); // Tell jetty about the new connection request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE,connection); 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 fed1f0960be..4f8f1f4619c 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 @@ -58,6 +58,7 @@ public class HandshakeRFC6455 implements WebSocketHandshake if (request.getExtensions() != null) { + response.setExtensions(request.getExtensions()); for (ExtensionConfig ext : request.getExtensions()) { response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName()); 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 b2b2c5f0ea2..3bbce057899 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 @@ -41,10 +41,11 @@ 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.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; import org.eclipse.jetty.websocket.server.examples.MyEchoSocket; import org.junit.AfterClass; import org.junit.Assert; @@ -72,7 +73,7 @@ public class WebSocketLoadRFC6455Test } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { } }; diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java index cce4f51d490..61276785da9 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; @@ -102,7 +103,7 @@ public class WebSocketServletRFCTest // Read frame echo'd back (hopefully a single binary frame) IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,1000); - WebSocketFrame binmsg = capture.getFrames().get(0); + Frame binmsg = capture.getFrames().get(0); int expectedSize = buf1.length + buf2.length + buf3.length; Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize)); @@ -225,7 +226,7 @@ public class WebSocketServletRFCTest // Read frame (hopefully close frame) IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,500); - WebSocketFrame cf = capture.getFrames().get(0); + Frame cf = capture.getFrames().get(0); CloseInfo close = new CloseInfo(cf); Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java index 5eb886513d7..a988982fc54 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java @@ -32,6 +32,7 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; @@ -86,7 +87,7 @@ public class Fuzzer public ByteBuffer asNetworkBuffer(List send) { int buflen = 0; - for (WebSocketFrame f : send) + for (Frame f : send) { buflen += f.getPayloadLength() + Generator.OVERHEAD; } @@ -213,7 +214,7 @@ public class Fuzzer if ((sendMode == SendMode.BULK) || (sendMode == SendMode.SLOW)) { int buflen = 0; - for (WebSocketFrame f : send) + for (Frame f : send) { buflen += f.getPayloadLength() + Generator.OVERHEAD; } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java index cd6459c5ca9..51f5d23a381 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java @@ -29,6 +29,17 @@ import org.junit.Test; public class TestABCase4 extends AbstractABCase { + // Allow Fuzzer / Generator to create bad frames for testing frame validation + private static class BadFrame extends WebSocketFrame + { + public BadFrame(byte opcode) + { + super(); + super.opcode = opcode; + // NOTE: Not setting Frame.Type intentionally + } + } + /** * Send opcode 3 (reserved) */ @@ -36,7 +47,7 @@ public class TestABCase4 extends AbstractABCase public void testCase4_1_1() throws Exception { List send = new ArrayList<>(); - send.add(new WebSocketFrame((byte)3)); // intentionally bad + send.add(new BadFrame((byte)3)); // intentionally bad List expect = new ArrayList<>(); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); @@ -64,7 +75,7 @@ public class TestABCase4 extends AbstractABCase byte payload[] = StringUtil.getUtf8Bytes("reserved payload"); List send = new ArrayList<>(); - send.add(new WebSocketFrame((byte)4).setPayload(payload)); // intentionally bad + send.add(new BadFrame((byte)4).setPayload(payload)); // intentionally bad List expect = new ArrayList<>(); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); @@ -91,7 +102,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)5)); // intentionally bad + send.add(new BadFrame((byte)5)); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); @@ -120,7 +131,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)6).setPayload("bad")); // intentionally bad + send.add(new BadFrame((byte)6).setPayload("bad")); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); @@ -149,7 +160,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)7).setPayload("bad")); // intentionally bad + send.add(new BadFrame((byte)7).setPayload("bad")); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); @@ -177,7 +188,7 @@ public class TestABCase4 extends AbstractABCase public void testCase4_2_1() throws Exception { List send = new ArrayList<>(); - send.add(new WebSocketFrame((byte)11)); // intentionally bad + send.add(new BadFrame((byte)11)); // intentionally bad List expect = new ArrayList<>(); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); @@ -203,7 +214,7 @@ public class TestABCase4 extends AbstractABCase public void testCase4_2_2() throws Exception { List send = new ArrayList<>(); - send.add(new WebSocketFrame((byte)12).setPayload("bad")); // intentionally bad + send.add(new BadFrame((byte)12).setPayload("bad")); // intentionally bad List expect = new ArrayList<>(); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); @@ -230,7 +241,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)13)); // intentionally bad + send.add(new BadFrame((byte)13)); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); @@ -259,7 +270,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)14).setPayload("bad")); // intentionally bad + send.add(new BadFrame((byte)14).setPayload("bad")); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); @@ -288,7 +299,7 @@ public class TestABCase4 extends AbstractABCase { List send = new ArrayList<>(); send.add(WebSocketFrame.text("hello")); - send.add(new WebSocketFrame((byte)15).setPayload("bad")); // intentionally bad + send.add(new BadFrame((byte)15).setPayload("bad")); // intentionally bad send.add(WebSocketFrame.ping()); List expect = new ArrayList<>(); 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 b14011d2977..d08b23082e6 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 @@ -34,6 +34,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -57,14 +59,15 @@ import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; +import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; import org.eclipse.jetty.websocket.server.helper.FinishedFuture; import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture; import org.junit.Assert; @@ -93,7 +96,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames private final Generator generator; private final Parser parser; private final IncomingFramesCapture incomingFrames; - private final WebSocketExtensionRegistry extensionRegistry; + private final WebSocketExtensionFactory extensionRegistry; private Socket socket; private OutputStream out; @@ -131,7 +134,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames this.incomingFrames = new IncomingFramesCapture(); - this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool); + this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool); } public void addExtensions(String xtension) @@ -220,26 +223,25 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames generator.configureFromExtensions(extensions); parser.configureFromExtensions(extensions); - // FIXME - // Iterator extIter; - // // Connect outgoings - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // Extension ext = extIter.next(); - // ext.setNextOutgoingFrames(outgoing); - // outgoing = ext; - // } - // - // // Connect incomings - // Collections.reverse(extensions); - // extIter = extensions.iterator(); - // while (extIter.hasNext()) - // { - // Extension ext = extIter.next(); - // ext.setNextIncomingFrames(incoming); - // incoming = ext; - // } + Iterator extIter; + // Connect outgoings + extIter = extensions.iterator(); + while (extIter.hasNext()) + { + Extension ext = extIter.next(); + ext.setNextOutgoingFrames(outgoing); + outgoing = ext; + } + + // Connect incomings + Collections.reverse(extensions); + extIter = extensions.iterator(); + while (extIter.hasNext()) + { + Extension ext = extIter.next(); + ext.setNextIncomingFrames(incoming); + incoming = ext; + } } // configure parser @@ -309,7 +311,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { LOG.debug("incoming({})",frame); int count = parseCount.incrementAndGet(); @@ -356,7 +358,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { ByteBuffer buf = generator.generate(frame); if (LOG.isDebugEnabled()) @@ -366,7 +368,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames BufferUtil.writeTo(buf,out); out.flush(); - if (frame.getOpCode() == OpCode.CLOSE) + if (frame.getType().getOpCode() == OpCode.CLOSE) { disconnect(); } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/echo/EchoBroadcastPingSocket.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/echo/EchoBroadcastPingSocket.java index f252585efc2..53f053924e3 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/echo/EchoBroadcastPingSocket.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/echo/EchoBroadcastPingSocket.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.websocket.server.examples.echo; +import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -45,8 +46,10 @@ public class EchoBroadcastPingSocket extends EchoBroadcastSocket while (!latch.await(10,TimeUnit.SECONDS)) { System.err.println("Ping"); - byte data[] = new byte[] - { (byte)1, (byte)2, (byte)3 }; + ByteBuffer data = ByteBuffer.allocate(3); + data.put(new byte[] + { (byte)1, (byte)2, (byte)3 }); + data.flip(); conn.ping(data); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/IncomingFramesCapture.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/IncomingFramesCapture.java index d229cf8eece..16219c5f12a 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/IncomingFramesCapture.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/IncomingFramesCapture.java @@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.IncomingFrames; import org.junit.Assert; public class IncomingFramesCapture implements IncomingFrames @@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames System.err.printf("Captured %d incoming frames%n",frames.size()); for (int i = 0; i < frames.size(); i++) { - WebSocketFrame frame = frames.get(i); + Frame frame = frames.get(i); System.err.printf("[%3d] %s%n",i,frame); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); } @@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames } @Override - public void incomingFrame(WebSocketFrame frame) + public void incomingFrame(Frame frame) { WebSocketFrame copy = new WebSocketFrame(frame); frames.add(copy); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/OutgoingFramesCapture.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/OutgoingFramesCapture.java index 8e6a840b90f..330e4269939 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/OutgoingFramesCapture.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/OutgoingFramesCapture.java @@ -28,9 +28,10 @@ import javax.net.websocket.SendResult; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.OutgoingFrames; import org.junit.Assert; public class OutgoingFramesCapture implements OutgoingFrames @@ -39,7 +40,7 @@ public class OutgoingFramesCapture implements OutgoingFrames { public C context; public Callback callback; - public WebSocketFrame frame; + public Frame frame; } private LinkedList frames = new LinkedList<>(); @@ -69,7 +70,7 @@ public class OutgoingFramesCapture implements OutgoingFrames System.out.printf("Captured %d outgoing writes%n",frames.size()); for (int i = 0; i < frames.size(); i++) { - WebSocketFrame frame = frames.get(i); + Frame frame = frames.get(i); System.out.printf("[%3d] %s%n",i,frame); System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); } @@ -94,9 +95,10 @@ public class OutgoingFramesCapture implements OutgoingFrames } @Override - public Future outgoingFrame(WebSocketFrame frame) throws IOException + public Future outgoingFrame(Frame frame) throws IOException { - frames.add(frame); + WebSocketFrame copy = new WebSocketFrame(frame); + frames.add(copy); return FinishedFuture.INSTANCE; } } diff --git a/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties index 7812b5df8fe..f593176caa4 100644 --- a/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-server/src/test/resources/jetty-logging.properties @@ -1,7 +1,7 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.LEVEL=WARN # org.eclipse.jetty.websocket.LEVEL=WARN -# org.eclipse.jetty.websocket.LEVEL=DEBUG +org.eclipse.jetty.websocket.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.WebSocketAsyncConnection.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG