Author: markt
Date: Fri Feb 17 23:17:57 2012
New Revision: 1245803

URL: http://svn.apache.org/viewvc?rev=1245803&view=rev
Log:
Move the frame header processing into the WsInputStream since the
fragmented frame processing will required header processing at this
level.

Added:
    tomcat/trunk/java/org/apache/catalina/websocket/WsFrameHeader.java
Modified:
    tomcat/trunk/java/org/apache/catalina/websocket/Constants.java
    tomcat/trunk/java/org/apache/catalina/websocket/StreamInbound.java
    tomcat/trunk/java/org/apache/catalina/websocket/WsInputStream.java

Modified: tomcat/trunk/java/org/apache/catalina/websocket/Constants.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/websocket/Constants.java?rev=1245803&r1=1245802&r2=1245803&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/websocket/Constants.java (original)
+++ tomcat/trunk/java/org/apache/catalina/websocket/Constants.java Fri Feb 17 
23:17:57 2012
@@ -21,4 +21,12 @@ package org.apache.catalina.websocket;
  */
 public class Constants {
     public static final String Package = "org.apache.catalina.websocket";
+
+    // OP Codes
+    public static final byte OPCODE_CONTINUATION = 0x00;
+    public static final byte OPCODE_TEXT = 0x01;
+    public static final byte OPCODE_BINARY = 0x02;
+    public static final byte OPCODE_CLOSE = 0x08;
+    public static final byte OPCODE_PING = 0x09;
+    public static final byte OPCODE_PONG = 0x0A;
 }

Modified: tomcat/trunk/java/org/apache/catalina/websocket/StreamInbound.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/websocket/StreamInbound.java?rev=1245803&r1=1245802&r2=1245803&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/websocket/StreamInbound.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/websocket/StreamInbound.java Fri Feb 
17 23:17:57 2012
@@ -21,7 +21,6 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 
-import org.apache.catalina.util.Conversions;
 import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.coyote.http11.upgrade.UpgradeOutbound;
 import org.apache.coyote.http11.upgrade.UpgradeProcessor;
@@ -30,18 +29,6 @@ import org.apache.tomcat.util.net.Abstra
 
 public abstract class StreamInbound implements UpgradeInbound {
 
-    // These attributes apply to the current frame being processed
-    private boolean fin = true;
-    private boolean rsv1 = false;
-    private boolean rsv2 = false;
-    private boolean rsv3 = false;
-    private int opCode = -1;
-    private long payloadLength = -1;
-
-    // These attributes apply to the message that may be spread over multiple
-    // frames
-    // TODO
-
     private UpgradeProcessor<?> processor = null;
     private WsOutbound outbound;
 
@@ -62,76 +49,30 @@ public abstract class StreamInbound impl
 
     @Override
     public SocketState onData() throws IOException {
-        // Must be start the start of a frame
-
-        // Read the first byte
-        int i = processor.read();
-
-        fin = (i & 0x80) > 0;
+        // Must be start the start of a frame or series of frames
+        WsInputStream wsIs = new WsInputStream(processor);
 
-        rsv1 = (i & 0x40) > 0;
-        rsv2 = (i & 0x20) > 0;
-        rsv3 = (i & 0x10) > 0;
-
-        if (rsv1 || rsv2 || rsv3) {
-            // TODO: Not supported.
-        }
-
-        opCode = (i & 0x0F);
+        WsFrameHeader header = wsIs.getFrameHeader();
+        byte opCode = header.getOpCode();
         validateOpCode(opCode);
 
-        // Read the next byte
-        i = processor.read();
-
-        // Client data must be masked and this isn't
-        if ((i & 0x80) == 0) {
-            // TODO: Better message
-            throw new IOException();
-        }
-
-        payloadLength = i & 0x7F;
-        if (payloadLength == 126) {
-            byte[] extended = new byte[2];
-            processor.read(extended);
-            payloadLength = Conversions.byteArrayToLong(extended);
-        } else if (payloadLength == 127) {
-            byte[] extended = new byte[8];
-            processor.read(extended);
-            payloadLength = Conversions.byteArrayToLong(extended);
+        if (opCode == Constants.OPCODE_BINARY) {
+            onBinaryData(wsIs);
+        } else if (opCode == Constants.OPCODE_TEXT) {
+            InputStreamReader r =
+                    new InputStreamReader(wsIs, B2CConverter.UTF_8);
+            onTextData(r);
+        } else {
+            // TODO i18n
+            throw new IOException("OpCode " + opCode + " not supported");
         }
-
-        byte[] mask = new byte[4];
-        processor.read(mask);
-
-        if (opCode == 1 || opCode == 2) {
-            WsInputStream wsIs = new WsInputStream(processor, mask,
-                    payloadLength);
-            if (opCode == 2) {
-                onBinaryData(wsIs);
-            } else {
-                InputStreamReader r =
-                        new InputStreamReader(wsIs, B2CConverter.UTF_8);
-                onTextData(r);
-            }
-        }
-
-        // TODO: Doesn't currently handle multi-frame messages. That will need
-        //       some refactoring.
-
-        // TODO: Per frame extension handling is not currently supported.
-
-        // TODO: Handle other control frames.
-
-        // TODO: Handle control frames appearing in the middle of a multi-frame
-        //       message
-
         return SocketState.UPGRADED;
     }
 
     protected abstract void onBinaryData(InputStream is) throws IOException;
     protected abstract void onTextData(Reader r) throws IOException;
 
-    private void validateOpCode(int opCode) throws IOException {
+    private void validateOpCode(byte opCode) throws IOException {
         switch (opCode) {
         case 0:
         case 1:

Added: tomcat/trunk/java/org/apache/catalina/websocket/WsFrameHeader.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/websocket/WsFrameHeader.java?rev=1245803&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/websocket/WsFrameHeader.java (added)
+++ tomcat/trunk/java/org/apache/catalina/websocket/WsFrameHeader.java Fri Feb 
17 23:17:57 2012
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.websocket;
+
+/**
+ * This class does not represent the complete frame header, just those parts of
+ * it that need to be exposed more widely than the {@link WsInputStream}.
+ */
+public class WsFrameHeader {
+
+    private final boolean fin;
+    private final boolean rsv1;
+    private final boolean rsv2;
+    private final boolean rsv3;
+    private final byte opCode;
+
+    public WsFrameHeader(int b) {
+        fin = (b & 0x80) > 0;
+
+        rsv1 = (b & 0x40) > 0;
+        rsv2 = (b & 0x20) > 0;
+        rsv3 = (b & 0x10) > 0;
+
+        opCode = (byte) (b & 0x0F);
+    }
+
+    public boolean getFin() {
+        return fin;
+    }
+
+    public boolean getRsv1() {
+        return rsv1;
+    }
+
+    public boolean getRsv2() {
+        return rsv2;
+    }
+
+    public boolean getRsv3() {
+        return rsv3;
+    }
+
+    public byte getOpCode() {
+        return opCode;
+    }
+
+
+}

Modified: tomcat/trunk/java/org/apache/catalina/websocket/WsInputStream.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/websocket/WsInputStream.java?rev=1245803&r1=1245802&r2=1245803&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/websocket/WsInputStream.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/websocket/WsInputStream.java Fri Feb 
17 23:17:57 2012
@@ -18,23 +18,66 @@ package org.apache.catalina.websocket;
 
 import java.io.IOException;
 
+import org.apache.catalina.util.Conversions;
 import org.apache.coyote.http11.upgrade.UpgradeProcessor;
 
 public class WsInputStream extends java.io.InputStream {
 
     private UpgradeProcessor<?> processor;
-    private byte[] mask;
+    private final WsFrameHeader wsFrameHeader;
+    private long payloadLength = -1;
+    private byte[] mask = new byte[4];
+
+
     private long remaining;
     private long read;
 
-    public WsInputStream(UpgradeProcessor<?> processor, byte[] mask,
-            long remaining) {
+    public WsInputStream(UpgradeProcessor<?> processor) throws IOException {
         this.processor = processor;
-        this.mask = mask;
-        this.remaining = remaining;
-        this.read = 0;
+
+        int i = processor.read();
+        this.wsFrameHeader = new WsFrameHeader(i);
+
+        // Client data must be masked
+        i = processor.read();
+        if ((i & 0x80) == 0) {
+            // TODO: StringManager / i18n
+            throw new IOException("Client frame not masked");
+        }
+
+        payloadLength = i & 0x7F;
+        if (payloadLength == 126) {
+            byte[] extended = new byte[2];
+            processor.read(extended);
+            payloadLength = Conversions.byteArrayToLong(extended);
+        } else if (payloadLength == 127) {
+            byte[] extended = new byte[8];
+            processor.read(extended);
+            payloadLength = Conversions.byteArrayToLong(extended);
+        }
+        remaining = payloadLength;
+
+        processor.read(mask);
+
+
+        // TODO: Doesn't currently handle multi-frame messages. That will need
+        //       some refactoring.
+
+        // TODO: Per frame extension handling is not currently supported.
+
+        // TODO: Handle other control frames.
+
+        // TODO: Handle control frames appearing in the middle of a multi-frame
+        //       message
     }
 
+    public WsFrameHeader getFrameHeader() {
+        return wsFrameHeader;
+    }
+
+
+    // ----------------------------------------------------- InputStream 
methods
+
     @Override
     public int read() throws IOException {
         if (remaining == 0) {
@@ -47,5 +90,4 @@ public class WsInputStream extends java.
         int masked = processor.read();
         return masked ^ mask[(int) ((read - 1) % 4)];
     }
-
 }



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

Reply via email to