diff options
-rw-r--r-- | core/src/main/java/fi/iki/elonen/NanoHTTPD.java | 23 | ||||
-rw-r--r-- | core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java | 21 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/NanoWSD.java (renamed from websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java) | 120 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java | 98 | ||||
-rw-r--r-- | websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java | 4 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java | 38 | ||||
-rw-r--r-- | websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java | 4 |
7 files changed, 189 insertions, 119 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java index 530ba94..906d435 100644 --- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java +++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java @@ -538,6 +538,8 @@ public abstract class NanoHTTPD { public static final int BUFSIZE = 8192; + public static final int MAX_HEADER_SIZE = 1024; + private final TempFileManager tempFileManager; private final OutputStream outputStream; @@ -646,17 +648,17 @@ public abstract class NanoHTTPD { throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but contains less than two boundary strings."); } - final int MAX_HEADER_SIZE = 1024; byte[] part_header_buff = new byte[MAX_HEADER_SIZE]; for (int bi = 0; bi < boundary_idxs.length - 1; bi++) { fbuf.position(boundary_idxs[bi]); int len = (fbuf.remaining() < MAX_HEADER_SIZE) ? fbuf.remaining() : MAX_HEADER_SIZE; fbuf.get(part_header_buff, 0, len); - ByteArrayInputStream bais = new ByteArrayInputStream(part_header_buff, 0, len); - BufferedReader in = new BufferedReader(new InputStreamReader(bais, Charset.forName(encoding))); + BufferedReader in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(part_header_buff, 0, len), Charset.forName(encoding)), len); + int headerLines = 0; // First line is boundary string String mpline = in.readLine(); + headerLines++; if (!mpline.contains(boundary)) { throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but chunk does not start with boundary."); } @@ -664,6 +666,7 @@ public abstract class NanoHTTPD { String part_name = null, file_name = null, content_type = null; // Parse the reset of the header lines mpline = in.readLine(); + headerLines++; while (mpline != null && mpline.trim().length() > 0) { Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(mpline); if (matcher.matches()) { @@ -683,10 +686,13 @@ public abstract class NanoHTTPD { content_type = matcher.group(2).trim(); } mpline = in.readLine(); + headerLines++; + } + int part_header_len = 0; + while (headerLines-- > 0) { + part_header_len = scipOverNewLine(part_header_buff, part_header_len); } - // Read the part data - int part_header_len = len - (int) in.skip(MAX_HEADER_SIZE); if (part_header_len >= len - 4) { throw new ResponseException(Response.Status.INTERNAL_ERROR, "Multipart header size exceeds MAX_HEADER_SIZE."); } @@ -721,6 +727,13 @@ public abstract class NanoHTTPD { } } + private int scipOverNewLine(byte[] part_header_buff, int index) { + while (part_header_buff[index] != '\n') { + index++; + } + return ++index; + } + /** * Decodes parameters in percent-encoded URI-format ( e.g. * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given diff --git a/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java b/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java index d2f5181..eef2f22 100644 --- a/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java +++ b/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java @@ -41,6 +41,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -51,9 +53,11 @@ import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; import org.junit.Test; import fi.iki.elonen.NanoHTTPD; +import fi.iki.elonen.NanoHTTPD.Response.Status; /** * @author Paul S. Hawke (paul.hawke@gmail.com) On: 5/19/13 at 5:36 PM @@ -81,8 +85,11 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt sb.append(';').append(k).append('=').append(parms.get(k)); } } - - return newFixedLengthResponse(sb.toString()); + if ("/chin".equals(uri)) { + return newFixedLengthResponse(Status.OK, "application/octet-stream", sb.toString()); + } else { + return newFixedLengthResponse(sb.toString()); + } } } @@ -160,7 +167,7 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt public void testPostRequestWithMultipartExtremEncodedParameters() throws Exception { this.testServer.response = "testPostRequestWithMultipartEncodedParameters"; - HttpPost httppost = new HttpPost("http://localhost:8192/"); + HttpPost httppost = new HttpPost("http://localhost:8192/chin"); MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, "sfsadfasdf", Charset.forName("UTF-8")); reqEntity.addPart("specialString", new StringBody("拖拉图片到浏览器,可以实现预览功能", "text/plain", Charset.forName("UTF-8"))); reqEntity.addPart("gender", new StringBody("图片名称", Charset.forName("UTF-8")) { @@ -171,11 +178,11 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt } }); httppost.setEntity(reqEntity); + HttpResponse response = this.httpclient.execute(httppost); - ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = this.httpclient.execute(httppost, responseHandler); + HttpEntity entity = response.getEntity(); + String responseBody = EntityUtils.toString(entity, "UTF-8"); - // assertEquals("POST:testPostRequestWithMultipartEncodedParameters-params=2;age=120;gender=Male", - // responseBody); + assertEquals("POST:testPostRequestWithMultipartEncodedParameters-params=2;gender=图片名称;specialString=拖拉图片到浏览器,可以实现预览功能", responseBody); } } diff --git a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/NanoWSD.java index 7f75f7a..6ccf21c 100644 --- a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java +++ b/websocket/src/main/java/fi/iki/elonen/NanoWSD.java @@ -48,11 +48,11 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import fi.iki.elonen.NanoWebSocketServer.WebSocketFrame.CloseCode; -import fi.iki.elonen.NanoWebSocketServer.WebSocketFrame.CloseFrame; -import fi.iki.elonen.NanoWebSocketServer.WebSocketFrame.OpCode; +import fi.iki.elonen.NanoWSD.WebSocketFrame.CloseCode; +import fi.iki.elonen.NanoWSD.WebSocketFrame.CloseFrame; +import fi.iki.elonen.NanoWSD.WebSocketFrame.OpCode; -public abstract class NanoWebSocketServer extends NanoHTTPD { +public abstract class NanoWSD extends NanoHTTPD { public static enum State { UNCONNECTED, @@ -62,7 +62,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { CLOSED } - public class WebSocket { + public static abstract class WebSocket { private final InputStream in; @@ -84,6 +84,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { WebSocket.this.state = State.CONNECTING; super.send(out); WebSocket.this.state = State.OPEN; + WebSocket.this.onOpen(); readWebsocket(); } }; @@ -92,10 +93,35 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { this.handshakeRequest = handshakeRequest; this.in = handshakeRequest.getInputStream(); - this.handshakeResponse.addHeader(NanoWebSocketServer.HEADER_UPGRADE, NanoWebSocketServer.HEADER_UPGRADE_VALUE); - this.handshakeResponse.addHeader(NanoWebSocketServer.HEADER_CONNECTION, NanoWebSocketServer.HEADER_CONNECTION_VALUE); - } - + this.handshakeResponse.addHeader(NanoWSD.HEADER_UPGRADE, NanoWSD.HEADER_UPGRADE_VALUE); + this.handshakeResponse.addHeader(NanoWSD.HEADER_CONNECTION, NanoWSD.HEADER_CONNECTION_VALUE); + } + + public boolean isOpen(){ + return state == State.OPEN; + } + + protected abstract void onOpen(); + protected abstract void onClose(CloseCode code, String reason, boolean initiatedByRemote); + protected abstract void onMessage(WebSocketFrame message); + protected abstract void onPong(WebSocketFrame pong); + protected abstract void onException(IOException exception); + + /** + * Debug method. <b>Do not Override unless for debug purposes!</b> + * + * @param frame The received WebSocket Frame. + */ + protected void debugFrameReceived(WebSocketFrame frame){} + + /** + * Debug method. <b>Do not Override unless for debug purposes!</b><br> + * This method is called before actually sending the frame. + * + * @param frame The sent WebSocket Frame. + */ + protected void debugFrameSent(WebSocketFrame frame){} + public void close(CloseCode code, String reason, boolean initiatedByRemote) throws IOException { State oldState = this.state; this.state = State.CLOSING; @@ -114,18 +140,18 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { try { this.in.close(); } catch (IOException e) { - NanoWebSocketServer.LOG.log(Level.FINE, "close failed", e); + NanoWSD.LOG.log(Level.FINE, "close failed", e); } } if (this.out != null) { try { this.out.close(); } catch (IOException e) { - NanoWebSocketServer.LOG.log(Level.FINE, "close failed", e); + NanoWSD.LOG.log(Level.FINE, "close failed", e); } } this.state = State.CLOSED; - onClose(this, code, reason, initiatedByRemote); + onClose(code, reason, initiatedByRemote); } // --------------------------------IO-------------------------------------- @@ -167,7 +193,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { if (this.continuousOpCode == null) { throw new WebSocketException(CloseCode.ProtocolError, "Continuous frame sequence was not started."); } - onMessage(this, new WebSocketFrame(this.continuousOpCode, this.continuousFrames)); + onMessage(new WebSocketFrame(this.continuousOpCode, this.continuousFrames)); this.continuousOpCode = null; this.continuousFrames.clear(); } else if (this.continuousOpCode == null) { @@ -180,19 +206,19 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { } private void handleWebsocketFrame(WebSocketFrame frame) throws IOException { - onFrameReceived(frame); + debugFrameReceived(frame); if (frame.getOpCode() == OpCode.Close) { handleCloseFrame(frame); } else if (frame.getOpCode() == OpCode.Ping) { sendFrame(new WebSocketFrame(OpCode.Pong, true, frame.getBinaryPayload())); } else if (frame.getOpCode() == OpCode.Pong) { - onPong(this, frame); + onPong(frame); } else if (!frame.isFin() || frame.getOpCode() == OpCode.Continuation) { handleFrameFragment(frame); } else if (this.continuousOpCode != null) { throw new WebSocketException(CloseCode.ProtocolError, "Continuous frame sequence not completed."); } else if (frame.getOpCode() == OpCode.Text || frame.getOpCode() == OpCode.Binary) { - onMessage(this, frame); + onMessage(frame); } else { throw new WebSocketException(CloseCode.ProtocolError, "Non control or continuous frame expected."); } @@ -213,10 +239,10 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { handleWebsocketFrame(WebSocketFrame.read(this.in)); } } catch (CharacterCodingException e) { - onException(this, e); + onException(e); doClose(CloseCode.InvalidFramePayloadData, e.toString(), false); } catch (IOException e) { - onException(this, e); + onException(e); if (e instanceof WebSocketException) { doClose(((WebSocketException) e).getCode(), ((WebSocketException) e).getReason(), false); } @@ -234,7 +260,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { } public synchronized void sendFrame(WebSocketFrame frame) throws IOException { - onSendFrame(frame); + debugFrameSent(frame); frame.write(this.out); } } @@ -702,7 +728,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { /** * logger to log to. */ - private static final Logger LOG = Logger.getLogger(NanoWebSocketServer.class.getName()); + private static final Logger LOG = Logger.getLogger(NanoWSD.class.getName()); public static final String HEADER_UPGRADE = "upgrade"; @@ -749,10 +775,10 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { byte b2 = i < size ? buf[i++] : 0; int mask = 0x3F; - ar[a++] = NanoWebSocketServer.ALPHABET[b0 >> 2 & mask]; - ar[a++] = NanoWebSocketServer.ALPHABET[(b0 << 4 | (b1 & 0xFF) >> 4) & mask]; - ar[a++] = NanoWebSocketServer.ALPHABET[(b1 << 2 | (b2 & 0xFF) >> 6) & mask]; - ar[a++] = NanoWebSocketServer.ALPHABET[b2 & mask]; + ar[a++] = NanoWSD.ALPHABET[b0 >> 2 & mask]; + ar[a++] = NanoWSD.ALPHABET[(b0 << 4 | (b1 & 0xFF) >> 4) & mask]; + ar[a++] = NanoWSD.ALPHABET[(b1 << 2 | (b2 & 0xFF) >> 6) & mask]; + ar[a++] = NanoWSD.ALPHABET[b2 & mask]; } switch (size % 3) { case 1: @@ -765,79 +791,61 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { public static String makeAcceptKey(String key) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-1"); - String text = key + NanoWebSocketServer.WEBSOCKET_KEY_MAGIC; + String text = key + NanoWSD.WEBSOCKET_KEY_MAGIC; md.update(text.getBytes(), 0, text.length()); byte[] sha1hash = md.digest(); return encodeBase64(sha1hash); } - public NanoWebSocketServer(int port) { + public NanoWSD(int port) { super(port); } - public NanoWebSocketServer(String hostname, int port) { + public NanoWSD(String hostname, int port) { super(hostname, port); } private boolean isWebSocketConnectionHeader(Map<String, String> headers) { - String connection = headers.get(NanoWebSocketServer.HEADER_CONNECTION); - return connection != null && connection.toLowerCase().contains(NanoWebSocketServer.HEADER_CONNECTION_VALUE.toLowerCase()); + String connection = headers.get(NanoWSD.HEADER_CONNECTION); + return connection != null && connection.toLowerCase().contains(NanoWSD.HEADER_CONNECTION_VALUE.toLowerCase()); } protected boolean isWebsocketRequested(IHTTPSession session) { Map<String, String> headers = session.getHeaders(); - String upgrade = headers.get(NanoWebSocketServer.HEADER_UPGRADE); + String upgrade = headers.get(NanoWSD.HEADER_UPGRADE); boolean isCorrectConnection = isWebSocketConnectionHeader(headers); - boolean isUpgrade = NanoWebSocketServer.HEADER_UPGRADE_VALUE.equalsIgnoreCase(upgrade); + boolean isUpgrade = NanoWSD.HEADER_UPGRADE_VALUE.equalsIgnoreCase(upgrade); return isUpgrade && isCorrectConnection; } - protected abstract void onClose(WebSocket webSocket, CloseCode code, String reason, boolean initiatedByRemote); - - protected abstract void onException(WebSocket webSocket, IOException e); - // --------------------------------Listener-------------------------------- - protected void onFrameReceived(WebSocketFrame webSocket) { - // only for debugging - } - - protected abstract void onMessage(WebSocket webSocket, WebSocketFrame messageFrame); - - protected abstract void onPong(WebSocket webSocket, WebSocketFrame pongFrame); - - public void onSendFrame(WebSocketFrame webSocket) { - // only for debugging - } - - public WebSocket openWebSocket(IHTTPSession handshake) { - return new WebSocket(handshake); - } + protected abstract WebSocket openWebSocket(IHTTPSession handshake); @Override public Response serve(final IHTTPSession session) { Map<String, String> headers = session.getHeaders(); if (isWebsocketRequested(session)) { - if (!NanoWebSocketServer.HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION))) { + if (!NanoWSD.HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(NanoWSD.HEADER_WEBSOCKET_VERSION))) { return newFixedLengthResponse(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, - "Invalid Websocket-Version " + headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION)); + "Invalid Websocket-Version " + headers.get(NanoWSD.HEADER_WEBSOCKET_VERSION)); } - if (!headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_KEY)) { + if (!headers.containsKey(NanoWSD.HEADER_WEBSOCKET_KEY)) { return newFixedLengthResponse(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key"); } WebSocket webSocket = openWebSocket(session); Response handshakeResponse = webSocket.getHandshakeResponse(); try { - handshakeResponse.addHeader(NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_KEY))); + handshakeResponse.addHeader(NanoWSD.HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(NanoWSD.HEADER_WEBSOCKET_KEY))); } catch (NoSuchAlgorithmException e) { return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "The SHA-1 Algorithm required for websockets is not available on the server."); } - if (headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL)) { - handshakeResponse.addHeader(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL, headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL).split(",")[0]); + if (headers.containsKey(NanoWSD.HEADER_WEBSOCKET_PROTOCOL)) { + handshakeResponse.addHeader(NanoWSD.HEADER_WEBSOCKET_PROTOCOL, headers.get(NanoWSD.HEADER_WEBSOCKET_PROTOCOL).split(",")[0]); } return handshakeResponse; 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 index 8f6aa78..44e7068 100644 --- a/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java +++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java @@ -37,12 +37,13 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; -import fi.iki.elonen.NanoWebSocketServer; +import fi.iki.elonen.NanoWSD; +import fi.iki.elonen.NanoWSD.WebSocketFrame.CloseCode; /** * @author Paul S. Hawke (paul.hawke@gmail.com) On: 4/23/14 at 10:31 PM */ -public class DebugWebSocketServer extends NanoWebSocketServer { +public class DebugWebSocketServer extends NanoWSD { /** * logger to log to. @@ -56,47 +57,64 @@ public class DebugWebSocketServer extends NanoWebSocketServer { this.debug = debug; } - @Override - protected void onClose(WebSocket socket, WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { - if (this.debug) { - System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]") - + (reason != null && !reason.isEmpty() ? ": " + reason : "")); - } - } + @Override + protected WebSocket openWebSocket(IHTTPSession handshake) { + return new DebugWebSocket(this, handshake); + } + + private static class DebugWebSocket extends WebSocket{ + private final DebugWebSocketServer server; + + public DebugWebSocket(DebugWebSocketServer server, IHTTPSession handshakeRequest) { + super(handshakeRequest); + this.server = server; + } - @Override - protected void onException(WebSocket socket, IOException e) { - DebugWebSocketServer.LOG.log(Level.SEVERE, "exception occured", e); - } + @Override + protected void onOpen(){} - @Override - protected void onFrameReceived(WebSocketFrame frame) { - if (this.debug) { - System.out.println("R " + frame); - } - } + @Override + protected void onClose(CloseCode code, String reason, boolean initiatedByRemote) { + if(server.debug) { + System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]") + + (reason != null && !reason.isEmpty() ? ": " + reason : "")); + } + } - @Override - protected void onMessage(WebSocket socket, WebSocketFrame messageFrame) { - try { - messageFrame.setUnmasked(); - socket.sendFrame(messageFrame); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + @Override + protected void onMessage(WebSocketFrame message) { + try { + message.setUnmasked(); + sendFrame(message); + } catch (IOException e) { + throw new RuntimeException(e); + } + } - @Override - protected void onPong(WebSocket socket, WebSocketFrame pongFrame) { - if (this.debug) { - System.out.println("P " + pongFrame); - } - } + @Override + protected void onPong(WebSocketFrame pong) { + if (server.debug) { + System.out.println("P " + pong); + } + } - @Override - public void onSendFrame(WebSocketFrame frame) { - if (this.debug) { - System.out.println("S " + frame); - } - } + @Override + protected void onException(IOException exception) { + DebugWebSocketServer.LOG.log(Level.SEVERE, "exception occured", exception); + } + + @Override + protected void debugFrameReceived(WebSocketFrame frame) { + if (server.debug) { + System.out.println("R " + frame); + } + } + + @Override + protected void debugFrameSent(WebSocketFrame frame) { + if (server.debug) { + System.out.println("S " + frame); + } + } + } } 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 index 3060146..e7d7e3b 100644 --- a/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java +++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java @@ -35,13 +35,13 @@ package fi.iki.elonen.samples.echo; import java.io.IOException; -import fi.iki.elonen.NanoWebSocketServer; +import fi.iki.elonen.NanoWSD; 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(args.length > 0 ? Integer.parseInt(args[0]) : 9090, debugMode); + NanoWSD ws = new DebugWebSocketServer(args.length > 0 ? Integer.parseInt(args[0]) : 9090, debugMode); ws.start(); System.out.println("Server started, hit Enter to stop.\n"); try { diff --git a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java index 69aa943..243601b 100644 --- a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java +++ b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java @@ -38,6 +38,7 @@ import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.when; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -50,6 +51,8 @@ import org.mockito.runners.MockitoJUnitRunner; import fi.iki.elonen.NanoHTTPD.IHTTPSession; import fi.iki.elonen.NanoHTTPD.Response; +import fi.iki.elonen.NanoWSD.WebSocketFrame; +import fi.iki.elonen.NanoWSD.WebSocketFrame.CloseCode; @RunWith(MockitoJUnitRunner.class) public class WebSocketResponseHandlerTest { @@ -57,13 +60,34 @@ public class WebSocketResponseHandlerTest { @Mock private IHTTPSession session; - private NanoWebSocketServer nanoWebSocketServer; + private NanoWSD nanoWebSocketServer; private Map<String, String> headers; - + + private static class MockedWSD extends NanoWSD{ + public MockedWSD(int port) { + super(port); + } + + public MockedWSD(String hostname, int port) { + super(hostname, port); + } + + @Override + protected WebSocket openWebSocket(IHTTPSession handshake) { + return new WebSocket(handshake) { // Dummy websocket inner class. + @Override protected void onPong(WebSocketFrame pong) {} + @Override protected void onOpen() {} + @Override protected void onMessage(WebSocketFrame message) {} + @Override protected void onException(IOException exception) {} + @Override protected void onClose(CloseCode code, String reason, boolean initiatedByRemote) {} + }; + } + } + @Before public void setUp() { - this.nanoWebSocketServer = Mockito.mock(NanoWebSocketServer.class, Mockito.CALLS_REAL_METHODS); + this.nanoWebSocketServer = Mockito.mock(MockedWSD.class, Mockito.CALLS_REAL_METHODS); this.headers = new HashMap<String, String>(); this.headers.put("upgrade", "websocket"); @@ -89,8 +113,8 @@ public class WebSocketResponseHandlerTest { assertNotNull(handshakeResponse); - assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT), "HSmrc0sMlYUkAGmm5OPpG2HaGWk="); - assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL), "chat"); + assertEquals(handshakeResponse.getHeader(NanoWSD.HEADER_WEBSOCKET_ACCEPT), "HSmrc0sMlYUkAGmm5OPpG2HaGWk="); + assertEquals(handshakeResponse.getHeader(NanoWSD.HEADER_WEBSOCKET_PROTOCOL), "chat"); } @Test @@ -107,14 +131,14 @@ public class WebSocketResponseHandlerTest { public void testWrongConnectionHeaderReturnsNullResponse() { this.headers.put("connection", "Junk"); Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); - assertNull(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_UPGRADE)); + assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE)); } @Test public void testWrongUpgradeHeaderReturnsNullResponse() { this.headers.put("upgrade", "not a websocket"); Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); - assertNull(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_UPGRADE)); + assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE)); } @Test diff --git a/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java b/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java index e90ae71..d8b96ab 100644 --- a/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java +++ b/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java @@ -43,11 +43,11 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import fi.iki.elonen.NanoWebSocketServer; +import fi.iki.elonen.NanoWSD; public class EchoWebSocketsTest { - private static NanoWebSocketServer server; + private static NanoWSD server; @BeforeClass public static void setUp() throws Exception { |