Author: pero Date: Fri Apr 6 17:51:25 2012 New Revision: 1310506 URL: http://svn.apache.org/viewvc?rev=1310506&view=rev Log: Correct websocket protocol version detection
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java tomcat/tc7.0.x/trunk/test/org/apache/catalina/websocket/TestWebSocket.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java?rev=1310506&r1=1310505&r2=1310506&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java Fri Apr 6 17:51:25 2012 @@ -143,7 +143,7 @@ public abstract class WebSocketServlet e } } } - return true; + return false; } @@ -166,7 +166,7 @@ public abstract class WebSocketServlet e return result; } - + // ToDo: Use ThreadLocal pool sha1Helper private String getWebSocketAccept(String key) { synchronized (sha1Helper) { sha1Helper.reset(); Modified: tomcat/tc7.0.x/trunk/test/org/apache/catalina/websocket/TestWebSocket.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/websocket/TestWebSocket.java?rev=1310506&r1=1310505&r2=1310506&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/catalina/websocket/TestWebSocket.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/websocket/TestWebSocket.java Fri Apr 6 17:51:25 2012 @@ -16,6 +16,10 @@ */ package org.apache.catalina.websocket; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -28,21 +32,25 @@ import java.io.Writer; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import org.junit.Test; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.List; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.catalina.util.Base64; import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.C2BConverter; import org.apache.tomcat.util.buf.CharChunk; +import org.junit.Test; public class TestWebSocket extends TomcatBaseTest { private static final String CRLF = "\r\n"; + private static final byte[] WS_ACCEPT = + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes( + B2CConverter.ISO_8859_1); private OutputStream os; private InputStream is; @@ -56,36 +64,27 @@ public class TestWebSocket extends Tomca tomcat.start(); - // Open the socket - final String encoding = "ISO-8859-1"; - SocketAddress addr = new InetSocketAddress("localhost", getPort()); - Socket socket = new Socket(); - socket.setSoTimeout(10000); - socket.connect(addr, 10000); - os = socket.getOutputStream(); - Writer writer = new OutputStreamWriter(os, encoding); - is = socket.getInputStream(); - Reader r = new InputStreamReader(is, encoding); - BufferedReader reader = new BufferedReader(r); + WebSocketCLient client= new WebSocketCLient(); + // Send the WebSocket handshake - writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); - writer.write("Host: foo" + CRLF); - writer.write("Upgrade: websocket" + CRLF); - writer.write("Connection: upgrade" + CRLF); - writer.write("Sec-WebSocket-Version: 13" + CRLF); - writer.write("Sec-WebSocket-Key: TODO" + CRLF); - writer.write(CRLF); - writer.flush(); + client.writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); + client.writer.write("Host: foo" + CRLF); + client.writer.write("Upgrade: websocket" + CRLF); + client.writer.write("Connection: keep-alive, upgrade" + CRLF); + client.writer.write("Sec-WebSocket-Version: 13" + CRLF); + client.writer.write("Sec-WebSocket-Key: TODO" + CRLF); + client.writer.write(CRLF); + client.writer.flush(); // Make sure we got an upgrade response - String responseLine = reader.readLine(); + String responseLine = client.reader.readLine(); assertTrue(responseLine.startsWith("HTTP/1.1 101")); // Swallow the headers - String responseHeaderLine = reader.readLine(); + String responseHeaderLine = client.reader.readLine(); while (!responseHeaderLine.equals("")) { - responseHeaderLine = reader.readLine(); + responseHeaderLine = client.reader.readLine(); } // Now we can do WebSocket @@ -95,11 +94,153 @@ public class TestWebSocket extends Tomca assertEquals("foofoo",readMessage()); // Finished with the socket - socket.close(); + client.close(); + } + + @Test + public void testDetectWrongVersion() throws Exception { + Tomcat tomcat = getTomcatInstance(); + File appDir = new File(getBuildDirectory(), "webapps/examples"); + tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); + + tomcat.start(); + WebSocketCLient client= new WebSocketCLient(); + + // Send the WebSocket handshake + client.writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); + client.writer.write("Host: foo" + CRLF); + client.writer.write("Upgrade: websocket" + CRLF); + client.writer.write("Connection: upgrade" + CRLF); + client.writer.write("Sec-WebSocket-Version: 8" + CRLF); + client.writer.write("Sec-WebSocket-Key: TODO" + CRLF); + client.writer.write(CRLF); + client.writer.flush(); + + // Make sure we got an upgrade response + String responseLine = client.reader.readLine(); + assertTrue(responseLine.startsWith("HTTP/1.1 426")); + + // Swallow the headers + List<String> headerlines = new ArrayList<String>(); + + String responseHeaderLine = client.reader.readLine(); + while (!responseHeaderLine.equals("")) { + headerlines.add(responseHeaderLine); + responseHeaderLine = client.reader.readLine(); + } + + assertTrue(headerlines.contains("Sec-WebSocket-Version: 13")); + // Finished with the socket + client.close(); + } + + @Test + public void testNoConnection() throws Exception { + Tomcat tomcat = getTomcatInstance(); + File appDir = new File(getBuildDirectory(), "webapps/examples"); + tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); + + tomcat.start(); + WebSocketCLient client= new WebSocketCLient(); + + + // Send the WebSocket handshake + client.writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); + client.writer.write("Host: foo" + CRLF); + client.writer.write("Upgrade: websocket" + CRLF); + client.writer.write("Sec-WebSocket-Version: 13" + CRLF); + client.writer.write("Sec-WebSocket-Key: TODO" + CRLF); + client.writer.write(CRLF); + client.writer.flush(); + + // Make sure we got an upgrade response + String responseLine = client.reader.readLine(); + assertTrue(responseLine.startsWith("HTTP/1.1 400")); + + // Finished with the socket + client.close(); } + + @Test + public void testNoUpgrade() throws Exception { + Tomcat tomcat = getTomcatInstance(); + File appDir = new File(getBuildDirectory(), "webapps/examples"); + tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); + + tomcat.start(); + WebSocketCLient client= new WebSocketCLient(); + + // Send the WebSocket handshake + client.writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); + client.writer.write("Host: foo" + CRLF); + client.writer.write("Connection: upgrade" + CRLF); + client.writer.write("Sec-WebSocket-Version: 13" + CRLF); + client.writer.write("Sec-WebSocket-Key: TODO" + CRLF); + client.writer.write(CRLF); + client.writer.flush(); + + // Make sure we got an upgrade response + String responseLine = client.reader.readLine(); + assertTrue(responseLine.startsWith("HTTP/1.1 400")); + + // Finished with the socket + client.close(); + } + + @Test + public void testKey() throws Exception { + Tomcat tomcat = getTomcatInstance(); + File appDir = new File(getBuildDirectory(), "webapps/examples"); + tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); + + tomcat.start(); + WebSocketCLient client= new WebSocketCLient(); + + // Send the WebSocket handshake + client.writer.write("GET /examples/websocket/echoStream HTTP/1.1" + CRLF); + client.writer.write("Host: foo" + CRLF); + client.writer.write("Upgrade: websocket" + CRLF); + client.writer.write("Connection: upgrade" + CRLF); + client.writer.write("Sec-WebSocket-Version: 13" + CRLF); + client.writer.write("Sec-WebSocket-Key: TODO" + CRLF); + client.writer.write(CRLF); + client.writer.flush(); + + // Make sure we got an upgrade response + String responseLine = client.reader.readLine(); + assertTrue(responseLine.startsWith("HTTP/1.1 101")); + + // Swallow the headers + String accept = null; + + String responseHeaderLine = client.reader.readLine(); + while (!responseHeaderLine.equals("")) { + if(responseHeaderLine.startsWith("Sec-WebSocket-Accept: ")) { + accept = responseHeaderLine.substring(responseHeaderLine.indexOf(":")+2); + break; + } + responseHeaderLine = client.reader.readLine(); + } + assertTrue(accept != null); + MessageDigest sha1Helper = MessageDigest.getInstance("SHA1"); + sha1Helper.reset(); + sha1Helper.update("TODO".getBytes(B2CConverter.ISO_8859_1)); + String source = Base64.encode(sha1Helper.digest(WS_ACCEPT)); + assertEquals(source,accept); + + sha1Helper.reset(); + sha1Helper.update("TOD".getBytes(B2CConverter.ISO_8859_1)); + source = Base64.encode(sha1Helper.digest(WS_ACCEPT)); + assertFalse(source.equals(accept)); + // Finished with the socket + client.close(); + } + + + private void sendMessage(String message, boolean finalFragment) - throws IOException{ + throws IOException{ ByteChunk bc = new ByteChunk(8192); C2BConverter c2b = new C2BConverter(bc, "UTF-8"); c2b.convert(message); @@ -161,4 +302,34 @@ public class TestWebSocket extends Tomca return cc.toString(); } + + private class WebSocketCLient + { + // Open the socket + final String encoding = "ISO-8859-1"; + Socket socket ; + Writer writer ; + BufferedReader reader; + + private WebSocketCLient() { + SocketAddress addr = new InetSocketAddress("localhost", getPort()); + socket = new Socket(); + try { + socket.setSoTimeout(10000); + socket.connect(addr, 10000); + os = socket.getOutputStream(); + writer = new OutputStreamWriter(os, encoding); + is = socket.getInputStream(); + Reader r = new InputStreamReader(is, encoding); + reader = new BufferedReader(r); + } catch (Exception e) { + new RuntimeException(e); + } + } + + void close() throws IOException { + socket.close(); + } + + } } Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1310506&r1=1310505&r2=1310506&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Fri Apr 6 17:51:25 2012 @@ -56,6 +56,9 @@ <section name="Tomcat 7.0.28 (markt)"> <subsection name="Catalina"> <changelog> + <fix> + Correct websocket protocol version detection. (pero) + </fix> <add> Add new attributes of allow and deny to UserConfig. (kfujino) </add> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org