You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/06/27 16:07:42 UTC

svn commit: r1606103 - in /tomcat/trunk/java/org/apache/tomcat/websocket: ./ server/

Author: markt
Date: Fri Jun 27 14:07:41 2014
New Revision: 1606103

URL: http://svn.apache.org/r1606103
Log:
Plumbing to enable transformation / extension processing for outgoing server messages.

Modified:
    tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
    tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsFrameServer.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java Fri Jun 27 14:07:41 2014
@@ -283,4 +283,15 @@ public class PerMessageDeflate implement
             return next.validateRsvBits(i | RSV_BITMASK);
         }
     }
+
+
+    @Override
+    public List<MessagePart> sendMessagePart(List<MessagePart> messageParts) {
+        // TODO: Implement compression of sent messages
+        if (next == null) {
+            return messageParts;
+        } else {
+            return next.sendMessagePart(messageParts);
+        }
+    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java Fri Jun 27 14:07:41 2014
@@ -18,18 +18,44 @@ package org.apache.tomcat.websocket;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.List;
 
 import javax.websocket.Extension;
 
 /**
  * The internal representation of the transformation that a WebSocket extension
  * performs on a message.
- *
- * TODO Add support for transformation of outgoing data as well as incoming.
  */
 public interface Transformation {
 
     /**
+     * Sets the next transformation in the pipeline.
+     */
+    void setNext(Transformation t);
+
+    /**
+     * Validate that the RSV bit(s) required by this transformation are not
+     * being used by another extension. The implementation is expected to set
+     * any bits it requires before passing the set of in-use bits to the next
+     * transformation.
+     *
+     * @param i         The RSV bits marked as in use so far as an int in the
+     *                  range zero to seven with RSV1 as the MSB and RSV3 as the
+     *                  LSB
+     *
+     * @return <code>true</code> if the combination of RSV bits used by the
+     *         transformations in the pipeline do not conflict otherwise
+     *         <code>false</code>
+     */
+    boolean validateRsvBits(int i);
+
+    /**
+     * Obtain the extension that describes the information to be returned to the
+     * client.
+     */
+    Extension getExtensionResponse();
+
+    /**
      * Obtain more input data.
      *
      * @param opCode    The opcode for the frame currently being processed
@@ -56,29 +82,16 @@ public interface Transformation {
     boolean validateRsv(int rsv, byte opCode);
 
     /**
-     * Obtain the extension that describes the information to be returned to the
-     * client.
-     */
-    Extension getExtensionResponse();
-
-    /**
-     * Sets the next transformation in the pipeline.
-     */
-    void setNext(Transformation t);
-
-    /**
-     * Validate that the RSV bit(s) required by this transformation are not
-     * being used by another extension. The implementation is expected to set
-     * any bits it requires before passing the set of in-use bits to the next
-     * transformation.
+     * Takes the provided list of messages, transforms them, passes the
+     * transformed list on to the next transformation (if any) and then returns
+     * the resulting list of message parts after all of the transformations have
+     * been applied.
      *
-     * @param i         The RSV bits marked as in use so far as an int in the
-     *                  range zero to seven with RSV1 as the MSB and RSV3 as the
-     *                  LSB
+     * @param messageParts  The list of messages to be transformed
      *
-     * @return <code>true</code> if the combination of RSV bits used by the
-     *         transformations in the pipeline do not conflict otherwise
-     *         <code>false</code>
+     * @return  The list of messages after this any any subsequent
+     *          transformations have been applied. The size of the returned list
+     *          may be bigger or smaller than the size of the input list
      */
-    boolean validateRsvBits(int i);
+    List<MessagePart> sendMessagePart(List<MessagePart> messageParts);
 }

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java Fri Jun 27 14:07:41 2014
@@ -22,6 +22,7 @@ import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
+import java.util.List;
 
 import javax.websocket.CloseReason;
 import javax.websocket.CloseReason.CloseCodes;
@@ -691,6 +692,11 @@ public abstract class WsFrameBase {
     }
 
 
+    protected Transformation getTransformation() {
+        return transformation;
+    }
+
+
     private static enum State {
         NEW_FRAME, PARTIAL_HEADER, DATA
     }
@@ -757,6 +763,14 @@ public abstract class WsFrameBase {
                 return TransformationResult.OVERFLOW;
             }
         }
+
+
+        @Override
+        public List<MessagePart> sendMessagePart(List<MessagePart> messageParts) {
+            // TODO Masking should move to this method
+            // NO-OP send so simply return the message unchanged.
+            return messageParts;
+        }
     }
 
 
@@ -792,5 +806,11 @@ public abstract class WsFrameBase {
                 return TransformationResult.OVERFLOW;
             }
         }
+
+        @Override
+        public List<MessagePart> sendMessagePart(List<MessagePart> messageParts) {
+            // NO-OP send so simply return the message unchanged.
+            return messageParts;
+        }
     }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java Fri Jun 27 14:07:41 2014
@@ -61,6 +61,7 @@ public abstract class WsRemoteEndpointIm
 
     private final StateMachine stateMachine = new StateMachine();
 
+    private Transformation transformation = null;
     private boolean messagePartInProgress = false;
     private final Queue<MessagePart> messagePartQueue = new ArrayDeque<>();
     private final Object messagePartLock = new Object();
@@ -82,6 +83,12 @@ public abstract class WsRemoteEndpointIm
     private WsSession wsSession;
     private List<EncoderEntry> encoderEntries = new ArrayList<>();
 
+
+    protected void setTransformation(Transformation transformation) {
+        this.transformation = transformation;
+    }
+
+
     public long getSendTimeout() {
         return sendTimeout;
     }
@@ -249,8 +256,13 @@ public abstract class WsRemoteEndpointIm
 
         wsSession.updateLastActive();
 
-        MessagePart mp = new MessagePart(opCode, payload, last,
-                new EndMessageHandler(this, handler));
+        List<MessagePart> messageParts = new ArrayList<>();
+        messageParts.add(new MessagePart(opCode, payload, last,
+                new EndMessageHandler(this, handler)));
+
+        messageParts = transformation.sendMessagePart(messageParts);
+
+        MessagePart mp = messageParts.remove(0);
 
         boolean doWrite = false;
         synchronized (messagePartLock) {
@@ -277,6 +289,8 @@ public abstract class WsRemoteEndpointIm
                 messagePartInProgress = true;
                 doWrite = true;
             }
+            // Add any remaining messages to the queue
+            messagePartQueue.addAll(messageParts);
         }
         if (doWrite) {
             // Actual write has to be outside sync block to avoid possible

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java Fri Jun 27 14:07:41 2014
@@ -113,8 +113,7 @@ public class WsSession implements Sessio
             URI requestUri, Map<String,List<String>> requestParameterMap,
             String queryString, Principal userPrincipal, String httpSessionId,
             String subProtocol, Map<String,String> pathParameters,
-            boolean secure, EndpointConfig endpointConfig,
-            Transformation transformation) throws DeploymentException {
+            boolean secure, EndpointConfig endpointConfig) throws DeploymentException {
         this.localEndpoint = localEndpoint;
         this.wsRemoteEndpoint = wsRemoteEndpoint;
         this.wsRemoteEndpoint.setSession(this);

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java Fri Jun 27 14:07:41 2014
@@ -316,15 +316,15 @@ public class WsWebSocketContainer
                     sm.getString("wsWebSocketContainer.httpRequestFailed"), e);
         }
 
-        // Switch to WebSocket
-        WsRemoteEndpointImplClient wsRemoteEndpointClient =
-                new WsRemoteEndpointImplClient(channel);
+        // TODO Add extension/transformation support to the client
 
+        // Switch to WebSocket
+        WsRemoteEndpointImplClient wsRemoteEndpointClient = new WsRemoteEndpointImplClient(channel);
 
         WsSession wsSession = new WsSession(endpoint, wsRemoteEndpointClient,
                 this, null, null, null, null, null, subProtocol,
                 Collections.<String, String> emptyMap(), secure,
-                clientEndpointConfiguration, null);
+                clientEndpointConfiguration);
         endpoint.onOpen(wsSession, clientEndpointConfiguration);
         registerSession(endpoint, wsSession);
 

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsFrameServer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsFrameServer.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsFrameServer.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsFrameServer.java Fri Jun 27 14:07:41 2014
@@ -65,4 +65,11 @@ public class WsFrameServer extends WsFra
         // Data is from the client so it should be masked
         return true;
     }
+
+
+    @Override
+    protected Transformation getTransformation() {
+        // Overridden to make it visible to other classes in this package
+        return super.getTransformation();
+    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java Fri Jun 27 14:07:41 2014
@@ -123,9 +123,12 @@ public class WsHttpUpgradeHandler implem
                     handshakeRequest.getParameterMap(),
                     handshakeRequest.getQueryString(),
                     handshakeRequest.getUserPrincipal(), httpSessionId,
-                    subProtocol, pathParameters, secure, endpointConfig, transformation);
+                    subProtocol, pathParameters, secure, endpointConfig);
             WsFrameServer wsFrame = new WsFrameServer(sis, wsSession, transformation);
             sos.setWriteListener(new WsWriteListener(this, wsRemoteEndpointServer));
+            // WsFrame adds the necessary final transformations. Copy the
+            // completed transformation chain to the remote end point.
+            wsRemoteEndpointServer.setTransformation(wsFrame.getTransformation());
             ep.onOpen(wsSession, endpointConfig);
             webSocketContainer.registerSession(ep, wsSession);
             sis.setReadListener(new WsReadListener(this, wsFrame));

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java?rev=1606103&r1=1606102&r2=1606103&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java Fri Jun 27 14:07:41 2014
@@ -31,6 +31,7 @@ import javax.websocket.SendResult;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.websocket.Transformation;
 import org.apache.tomcat.websocket.WsRemoteEndpointImplBase;
 
 /**
@@ -58,8 +59,7 @@ public class WsRemoteEndpointImplServer 
     private volatile boolean close;
 
 
-    public WsRemoteEndpointImplServer(ServletOutputStream sos,
-            WsServerContainer serverContainer) {
+    public WsRemoteEndpointImplServer(ServletOutputStream sos, WsServerContainer serverContainer) {
         this.sos = sos;
         this.wsWriteTimeout = serverContainer.getTimeout();
         this.executorService = serverContainer.getExecutorService();
@@ -170,6 +170,13 @@ public class WsRemoteEndpointImplServer 
     }
 
 
+    @Override
+    protected void setTransformation(Transformation transformation) {
+        // Overridden purely so it is visible to other classes in this package
+        super.setTransformation(transformation);
+    }
+
+
     /**
      *
      * @param t             The throwable associated with any error that



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org