diff options
author | Paul Hawke <paul.hawke@gmail.com> | 2014-04-24 23:21:55 -0500 |
---|---|---|
committer | Paul Hawke <paul.hawke@gmail.com> | 2014-04-24 23:21:55 -0500 |
commit | 84a1ab453aafe41149fab0e663b49d85cf0896cb (patch) | |
tree | 0e858c7fa82ea5b6971781e73329945018a15de7 /websocket/src/main/java/fi/iki | |
parent | 44f52c7b241f235d887ab57bf0ffd97a8ce0f5c4 (diff) | |
download | nanohttpd-84a1ab453aafe41149fab0e663b49d85cf0896cb.tar.gz |
Simplified the test using Mockito, and expanded what was being tested along with some other minor cleanup
Diffstat (limited to 'websocket/src/main/java/fi/iki')
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/IWebSocketFactory.java (renamed from websocket/src/main/java/fi/iki/elonen/WebSocketFactory.java) | 2 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java | 17 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/WebSocket.java | 42 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/WebSocketResponseHandler.java | 33 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocket.java | 67 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java | 22 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java | 22 |
7 files changed, 161 insertions, 44 deletions
diff --git a/websocket/src/main/java/fi/iki/elonen/WebSocketFactory.java b/websocket/src/main/java/fi/iki/elonen/IWebSocketFactory.java index 4a4be16..3e38cd2 100644 --- a/websocket/src/main/java/fi/iki/elonen/WebSocketFactory.java +++ b/websocket/src/main/java/fi/iki/elonen/IWebSocketFactory.java @@ -2,6 +2,6 @@ package fi.iki.elonen; import fi.iki.elonen.NanoHTTPD.IHTTPSession; -public interface WebSocketFactory { +public interface IWebSocketFactory { WebSocket openWebSocket(IHTTPSession handshake); } diff --git a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java index 44a5e9c..0712371 100644 --- a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java +++ b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java @@ -1,10 +1,11 @@ package fi.iki.elonen; -public class NanoWebSocketServer extends NanoHTTPD implements WebSocketFactory { - +public class NanoWebSocketServer extends NanoHTTPD implements IWebSocketFactory { + public static final String MISSING_FACTORY_MESSAGE = "You must either override this method or supply a WebSocketFactory in the constructor"; + private final WebSocketResponseHandler responseHandler; - + public NanoWebSocketServer(int port) { super(port); responseHandler = new WebSocketResponseHandler(this); @@ -14,17 +15,17 @@ public class NanoWebSocketServer extends NanoHTTPD implements WebSocketFactory { super(hostname, port); responseHandler = new WebSocketResponseHandler(this); } - - public NanoWebSocketServer(int port, WebSocketFactory webSocketFactory) { + + public NanoWebSocketServer(int port, IWebSocketFactory webSocketFactory) { super(port); responseHandler = new WebSocketResponseHandler(webSocketFactory); } - public NanoWebSocketServer(String hostname, int port,WebSocketFactory webSocketFactory) { + public NanoWebSocketServer(String hostname, int port, IWebSocketFactory webSocketFactory) { super(hostname, port); responseHandler = new WebSocketResponseHandler(webSocketFactory); } - + @Override public Response serve(IHTTPSession session) { Response candidate = responseHandler.serve(session); @@ -32,7 +33,7 @@ public class NanoWebSocketServer extends NanoHTTPD implements WebSocketFactory { } public WebSocket openWebSocket(IHTTPSession handshake) { - throw new Error("You must either override this method or supply a WebSocketFactory in the cosntructor"); + throw new Error(MISSING_FACTORY_MESSAGE); } } diff --git a/websocket/src/main/java/fi/iki/elonen/WebSocket.java b/websocket/src/main/java/fi/iki/elonen/WebSocket.java index ba1a446..22b07fb 100644 --- a/websocket/src/main/java/fi/iki/elonen/WebSocket.java +++ b/websocket/src/main/java/fi/iki/elonen/WebSocket.java @@ -12,20 +12,24 @@ import java.util.LinkedList; import java.util.List; public abstract class WebSocket { - protected final InputStream in; - protected /*final*/ OutputStream out; + public static enum State { + UNCONNECTED, CONNECTING, OPEN, CLOSING, CLOSED + } + + protected InputStream in; + + protected OutputStream out; protected WebSocketFrame.OpCode continuousOpCode = null; + protected List<WebSocketFrame> continuousFrames = new LinkedList<WebSocketFrame>(); protected State state = State.UNCONNECTED; - public static enum State { - UNCONNECTED, CONNECTING, OPEN, CLOSING, CLOSED - } - protected final NanoHTTPD.IHTTPSession handshakeRequest; - protected final NanoHTTPD.Response handshakeResponse = new NanoHTTPD.Response(NanoHTTPD.Response.Status.SWITCH_PROTOCOL, null, (InputStream) null) { + + protected final NanoHTTPD.Response handshakeResponse = new NanoHTTPD.Response( + NanoHTTPD.Response.Status.SWITCH_PROTOCOL, null, (InputStream) null) { @Override protected void send(OutputStream out) { WebSocket.this.out = out; @@ -40,8 +44,18 @@ public abstract class WebSocket { this.handshakeRequest = handshakeRequest; this.in = handshakeRequest.getInputStream(); - handshakeResponse.addHeader(WebSocketResponseHandler.HEADER_UPGRADE, WebSocketResponseHandler.HEADER_UPGRADE_VALUE); - handshakeResponse.addHeader(WebSocketResponseHandler.HEADER_CONNECTION, WebSocketResponseHandler.HEADER_CONNECTION_VALUE); + handshakeResponse.addHeader(WebSocketResponseHandler.HEADER_UPGRADE, + WebSocketResponseHandler.HEADER_UPGRADE_VALUE); + handshakeResponse.addHeader(WebSocketResponseHandler.HEADER_CONNECTION, + WebSocketResponseHandler.HEADER_CONNECTION_VALUE); + } + + public NanoHTTPD.IHTTPSession getHandshakeRequest() { + return handshakeRequest; + } + + public NanoHTTPD.Response getHandshakeResponse() { + return handshakeResponse; } // --------------------------------IO-------------------------------------- @@ -190,14 +204,4 @@ public abstract class WebSocket { doClose(code, reason, false); } } - - // --------------------------------Getters--------------------------------- - - public NanoHTTPD.IHTTPSession getHandshakeRequest() { - return handshakeRequest; - } - - public NanoHTTPD.Response getHandshakeResponse() { - return handshakeResponse; - } } diff --git a/websocket/src/main/java/fi/iki/elonen/WebSocketResponseHandler.java b/websocket/src/main/java/fi/iki/elonen/WebSocketResponseHandler.java index 2805889..5c042af 100644 --- a/websocket/src/main/java/fi/iki/elonen/WebSocketResponseHandler.java +++ b/websocket/src/main/java/fi/iki/elonen/WebSocketResponseHandler.java @@ -19,38 +19,40 @@ public class WebSocketResponseHandler { public static final String HEADER_WEBSOCKET_PROTOCOL = "sec-websocket-protocol"; public final static String WEBSOCKET_KEY_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - private final WebSocketFactory webSocketFactory; - public WebSocketResponseHandler(WebSocketFactory webSocketFactory) { - super(); + private final IWebSocketFactory webSocketFactory; + + public WebSocketResponseHandler(IWebSocketFactory webSocketFactory) { this.webSocketFactory = webSocketFactory; } - + public Response serve(final IHTTPSession session) { Map<String, String> headers = session.getHeaders(); if (isWebsocketRequested(session)) { - if (!HEADER_UPGRADE_VALUE.equalsIgnoreCase(headers.get(HEADER_UPGRADE)) - || !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))) { - return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Invalid Websocket-Version " + headers.get(HEADER_WEBSOCKET_VERSION)); + return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, + "Invalid Websocket-Version " + headers.get(HEADER_WEBSOCKET_VERSION)); } + if (!headers.containsKey(HEADER_WEBSOCKET_KEY)) { - return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key"); + return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, + "Missing Websocket-Key"); } WebSocket webSocket = webSocketFactory.openWebSocket(session); + Response handshakeResponse = webSocket.getHandshakeResponse(); try { - webSocket.getHandshakeResponse().addHeader(HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(HEADER_WEBSOCKET_KEY))); + handshakeResponse.addHeader(HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(HEADER_WEBSOCKET_KEY))); } catch (NoSuchAlgorithmException e) { - return new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "The SHA-1 Algorithm required for websockets is not available on the server."); + return new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, + "The SHA-1 Algorithm required for websockets is not available on the server."); } + if (headers.containsKey(HEADER_WEBSOCKET_PROTOCOL)) { - webSocket.getHandshakeResponse().addHeader(HEADER_WEBSOCKET_PROTOCOL, headers.get(HEADER_WEBSOCKET_PROTOCOL).split(",")[0]); + handshakeResponse.addHeader(HEADER_WEBSOCKET_PROTOCOL, headers.get(HEADER_WEBSOCKET_PROTOCOL).split(",")[0]); } - return webSocket.getHandshakeResponse(); + + return handshakeResponse; } else { return null; } @@ -77,7 +79,6 @@ public class WebSocketResponseHandler { return encodeBase64(sha1hash); } - private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); /** diff --git a/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocket.java b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocket.java new file mode 100644 index 0000000..badd7ee --- /dev/null +++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocket.java @@ -0,0 +1,67 @@ +package fi.iki.elonen.samples.echo; + +import fi.iki.elonen.NanoHTTPD; +import fi.iki.elonen.WebSocket; +import fi.iki.elonen.WebSocketFrame; + +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); + this.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/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java new file mode 100644 index 0000000..5faf72a --- /dev/null +++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java @@ -0,0 +1,22 @@ +package fi.iki.elonen.samples.echo; + +import fi.iki.elonen.NanoWebSocketServer; +import fi.iki.elonen.WebSocket; + +/** +* @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 + public WebSocket openWebSocket(IHTTPSession handshake) { + return new DebugWebSocket(handshake, debug); + } +} diff --git a/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java b/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java new file mode 100644 index 0000000..b28a42c --- /dev/null +++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java @@ -0,0 +1,22 @@ +package fi.iki.elonen.samples.echo; + +import fi.iki.elonen.NanoWebSocketServer; + +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"); + } + +} + |