diff options
author | Paul Hawke <paul.hawke@gmail.com> | 2014-04-23 23:08:57 -0500 |
---|---|---|
committer | Paul Hawke <paul.hawke@gmail.com> | 2014-04-23 23:08:57 -0500 |
commit | c6c080a6f4377fb18fc869111714e9514c36331a (patch) | |
tree | 1ac1f8ad3486e39bd2591bd5d603dcd09de8f0e9 /websocket | |
parent | 6d3737c76afdb1c991bf8d96e3dd2cc622435f09 (diff) | |
download | nanohttpd-c6c080a6f4377fb18fc869111714e9514c36331a.tar.gz |
websockets: final polish before release. Tested on IE, Chrome and Firefox
Diffstat (limited to 'websocket')
-rw-r--r-- | websocket/pom.xml | 2 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java (renamed from websocket/src/main/java/fi/iki/elonen/NanoWSD.java) | 19 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/WebSocket.java | 4 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/DebugWebSocket.java | 61 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/DebugWebSocketServer.java | 19 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/EchoSocket.java | 70 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/EchoSocketSample.java | 20 | ||||
-rw-r--r-- | websocket/src/test/resources/echo-test.html | 58 |
8 files changed, 174 insertions, 79 deletions
diff --git a/websocket/pom.xml b/websocket/pom.xml index 04ecc4b..7d94041 100644 --- a/websocket/pom.xml +++ b/websocket/pom.xml @@ -75,7 +75,7 @@ </descriptorRefs> <archive> <manifest> - <mainClass>fi.iki.elonen.NanoWSD</mainClass> + <mainClass>fi.iki.elonen.NanoWebSocketServer</mainClass> </manifest> </archive> </configuration> diff --git a/websocket/src/main/java/fi/iki/elonen/NanoWSD.java b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java index 2b2933a..7a5e588 100644 --- a/websocket/src/main/java/fi/iki/elonen/NanoWSD.java +++ b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java @@ -6,7 +6,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Map; -public abstract class NanoWSD extends NanoHTTPD { +public abstract class NanoWebSocketServer extends NanoHTTPD { public static final String HEADER_UPGRADE = "upgrade"; public static final String HEADER_UPGRADE_VALUE = "websocket"; public static final String HEADER_CONNECTION = "connection"; @@ -19,11 +19,11 @@ public abstract class NanoWSD extends NanoHTTPD { public final static String WEBSOCKET_KEY_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - public NanoWSD(int port) { + public NanoWebSocketServer(int port) { super(port); } - public NanoWSD(String hostname, int port) { + public NanoWebSocketServer(String hostname, int port) { super(hostname, port); } @@ -32,7 +32,7 @@ public abstract class NanoWSD extends NanoHTTPD { Map<String, String> headers = session.getHeaders(); if (isWebsocketRequested(session)) { if (!HEADER_UPGRADE_VALUE.equalsIgnoreCase(headers.get(HEADER_UPGRADE)) - || !HEADER_CONNECTION_VALUE.equalsIgnoreCase(headers.get(HEADER_CONNECTION))) { + || !isWebSocketConnectionHeader(session.getHeaders())) { return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Invalid Websocket handshake"); } if (!HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(HEADER_WEBSOCKET_VERSION))) { @@ -61,8 +61,15 @@ public abstract class NanoWSD extends NanoHTTPD { protected boolean isWebsocketRequested(IHTTPSession session) { Map<String, String> headers = session.getHeaders(); - return ((HEADER_UPGRADE_VALUE.equalsIgnoreCase(headers.get(HEADER_UPGRADE))) - && (HEADER_CONNECTION_VALUE.equalsIgnoreCase(headers.get(HEADER_CONNECTION)))); + String upgrade = headers.get(HEADER_UPGRADE); + boolean isCorrectConnection = isWebSocketConnectionHeader(headers); + boolean isUpgrade = HEADER_UPGRADE_VALUE.equalsIgnoreCase(upgrade); + return (isUpgrade && isCorrectConnection); + } + + private boolean isWebSocketConnectionHeader(Map<String, String> headers) { + String connection = headers.get(HEADER_CONNECTION); + return (connection != null && connection.toLowerCase().contains(HEADER_CONNECTION_VALUE.toLowerCase())); } public static String makeAcceptKey(String key) throws NoSuchAlgorithmException { diff --git a/websocket/src/main/java/fi/iki/elonen/WebSocket.java b/websocket/src/main/java/fi/iki/elonen/WebSocket.java index dcba8c0..84bf259 100644 --- a/websocket/src/main/java/fi/iki/elonen/WebSocket.java +++ b/websocket/src/main/java/fi/iki/elonen/WebSocket.java @@ -40,8 +40,8 @@ public abstract class WebSocket { this.handshakeRequest = handshakeRequest; this.in = handshakeRequest.getInputStream(); - handshakeResponse.addHeader(NanoWSD.HEADER_UPGRADE, NanoWSD.HEADER_UPGRADE_VALUE); - handshakeResponse.addHeader(NanoWSD.HEADER_CONNECTION, NanoWSD.HEADER_CONNECTION_VALUE); + handshakeResponse.addHeader(NanoWebSocketServer.HEADER_UPGRADE, NanoWebSocketServer.HEADER_UPGRADE_VALUE); + handshakeResponse.addHeader(NanoWebSocketServer.HEADER_CONNECTION, NanoWebSocketServer.HEADER_CONNECTION_VALUE); } // --------------------------------IO-------------------------------------- diff --git a/websocket/src/test/java/fi/iki/elonen/DebugWebSocket.java b/websocket/src/test/java/fi/iki/elonen/DebugWebSocket.java new file mode 100644 index 0000000..e6c66ad --- /dev/null +++ b/websocket/src/test/java/fi/iki/elonen/DebugWebSocket.java @@ -0,0 +1,61 @@ +package fi.iki.elonen; + +import java.io.IOException; + +/** +* @author Paul S. Hawke (paul.hawke@gmail.com) +* On: 4/23/14 at 10:34 PM +*/ +class DebugWebSocket extends WebSocket { + private final boolean DEBUG; + + public DebugWebSocket(NanoHTTPD.IHTTPSession handshake, boolean debug) { + super(handshake); + DEBUG = debug; + } + + @Override + protected void onPong(WebSocketFrame pongFrame) { + if (DEBUG) { + System.out.println("P " + pongFrame); + } + } + + @Override + protected void onMessage(WebSocketFrame messageFrame) { + try { + messageFrame.setUnmasked(); + sendFrame(messageFrame); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { + if (DEBUG) { + System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]") + (reason != null && !reason.isEmpty() ? ": " + reason : "")); + } + } + + @Override + protected void onException(IOException e) { + e.printStackTrace(); + } + + @Override + protected void handleWebsocketFrame(WebSocketFrame frame) throws IOException { + if (DEBUG) { + System.out.println("R " + frame); + } + super.handleWebsocketFrame(frame); + } + + @Override + public synchronized void sendFrame(WebSocketFrame frame) throws IOException { + if (DEBUG) { + System.out.println("S " + frame); + } + super.sendFrame(frame); + } +} diff --git a/websocket/src/test/java/fi/iki/elonen/DebugWebSocketServer.java b/websocket/src/test/java/fi/iki/elonen/DebugWebSocketServer.java new file mode 100644 index 0000000..49fbe4d --- /dev/null +++ b/websocket/src/test/java/fi/iki/elonen/DebugWebSocketServer.java @@ -0,0 +1,19 @@ +package fi.iki.elonen; + +/** +* @author Paul S. Hawke (paul.hawke@gmail.com) +* On: 4/23/14 at 10:31 PM +*/ +class DebugWebSocketServer extends NanoWebSocketServer { + private final boolean debug; + + public DebugWebSocketServer(int port, boolean debug) { + super(port); + this.debug = debug; + } + + @Override + protected WebSocket openWebSocket(IHTTPSession handshake) { + return new DebugWebSocket(handshake, debug); + } +} diff --git a/websocket/src/test/java/fi/iki/elonen/EchoSocket.java b/websocket/src/test/java/fi/iki/elonen/EchoSocket.java deleted file mode 100644 index ef39796..0000000 --- a/websocket/src/test/java/fi/iki/elonen/EchoSocket.java +++ /dev/null @@ -1,70 +0,0 @@ -package fi.iki.elonen; - -import java.io.IOException; - -public class EchoSocket { - public static void main(String[] args) throws IOException { - final boolean DEBUG = args.length >= 2 && args[1].toLowerCase().equals("-d"); - NanoWSD ws = new NanoWSD(Integer.parseInt(args[0])) { - @Override - protected WebSocket openWebSocket(IHTTPSession handshake) { - return new WebSocket(handshake) { - @Override - protected void onPong(WebSocketFrame pongFrame) { - if (DEBUG) { - System.out.println("P " + pongFrame); - } - } - - @Override - protected void onMessage(WebSocketFrame messageFrame) { - try { - messageFrame.setUnmasked(); - sendFrame(messageFrame); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { - if (DEBUG) { - System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]") + (reason != null && !reason.isEmpty() ? ": " + reason : "")); - } - } - - @Override - protected void onException(IOException e) { - e.printStackTrace(); - } - - @Override - protected void handleWebsocketFrame(WebSocketFrame frame) throws IOException { - if (DEBUG) { - System.out.println("R " + frame); - } - super.handleWebsocketFrame(frame); - } - - @Override - public synchronized void sendFrame(WebSocketFrame frame) throws IOException { - if (DEBUG) { - System.out.println("S " + frame); - } - super.sendFrame(frame); - } - }; - } - }; - - ws.start(); - System.out.println("Server started, hit Enter to stop.\n"); - try { - System.in.read(); - } catch (IOException ignored) { - } - ws.stop(); - System.out.println("Server stopped.\n"); - } -} - diff --git a/websocket/src/test/java/fi/iki/elonen/EchoSocketSample.java b/websocket/src/test/java/fi/iki/elonen/EchoSocketSample.java new file mode 100644 index 0000000..091dfc0 --- /dev/null +++ b/websocket/src/test/java/fi/iki/elonen/EchoSocketSample.java @@ -0,0 +1,20 @@ +package fi.iki.elonen; + +import java.io.IOException; + +public class EchoSocketSample { + public static void main(String[] args) throws IOException { + final boolean debugMode = args.length >= 2 && args[1].toLowerCase().equals("-d"); + NanoWebSocketServer ws = new DebugWebSocketServer(Integer.parseInt(args[0]), debugMode); + ws.start(); + System.out.println("Server started, hit Enter to stop.\n"); + try { + System.in.read(); + } catch (IOException ignored) { + } + ws.stop(); + System.out.println("Server stopped.\n"); + } + +} + diff --git a/websocket/src/test/resources/echo-test.html b/websocket/src/test/resources/echo-test.html new file mode 100644 index 0000000..4b60b80 --- /dev/null +++ b/websocket/src/test/resources/echo-test.html @@ -0,0 +1,58 @@ +<html> +<head> + <meta charset="utf-8"/> + <title>WebSocket Test</title> + <script language="javascript" type="text/javascript"> + var wsUri = "ws://localhost:9090/"; + var output; + function init() { + output = document.getElementById("output"); + testWebSocket(); + } + function testWebSocket() { + websocket = new WebSocket(wsUri); + websocket.onopen = function (evt) { + onOpen(evt) + }; + websocket.onclose = function (evt) { + onClose(evt) + }; + websocket.onmessage = function (evt) { + onMessage(evt) + }; + websocket.onerror = function (evt) { + onError(evt) + }; + } + function onOpen(evt) { + writeToScreen("CONNECTED"); + doSend("WebSocket rocks"); + } + function onClose(evt) { + writeToScreen("DISCONNECTED"); + } + function onMessage(evt) { + writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data + '</span>'); + websocket.close(); + } + function onError(evt) { + writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data); + } + function doSend(message) { + writeToScreen("SENT: " + message); + websocket.send(message); + } + function writeToScreen(message) { + var pre = document.createElement("p"); + pre.style.wordWrap = "break-word"; + pre.innerHTML = message; + output.appendChild(pre); + } + window.addEventListener("load", init, false); </script> +</head> +<body> +<h2>WebSocket Test</h2> + +<div id="output"></div> +</body> +</html>
\ No newline at end of file |