From 8b07bbd9f07ddcc9a385441d9f79f62473cefcfc Mon Sep 17 00:00:00 2001 From: nkzawa Date: Wed, 12 Jul 2017 12:31:41 +0900 Subject: [PATCH 1/5] utf8: add strict option --- src/main/java/io/socket/utf8/UTF8.java | 45 +++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/socket/utf8/UTF8.java b/src/main/java/io/socket/utf8/UTF8.java index 511d478..e714579 100644 --- a/src/main/java/io/socket/utf8/UTF8.java +++ b/src/main/java/io/socket/utf8/UTF8.java @@ -18,6 +18,12 @@ public final class UTF8 { private UTF8 () {} public static String encode(String string) throws UTF8Exception { + return encode(string, new Options()); + } + + public static String encode(String string, Options opts) throws UTF8Exception { + boolean strict = opts.strict; + int[] codePoints = ucs2decode(string); int length = codePoints.length; int index = -1; @@ -25,18 +31,24 @@ public final class UTF8 { StringBuilder byteString = new StringBuilder(); while (++index < length) { codePoint = codePoints[index]; - byteString.append(encodeCodePoint(codePoint)); + byteString.append(encodeCodePoint(codePoint, strict)); } return byteString.toString(); } public static String decode(String byteString) throws UTF8Exception { + return decode(byteString, new Options()); + } + + public static String decode(String byteString, Options opts) throws UTF8Exception { + boolean strict = opts.strict; + byteArray = ucs2decode(byteString); byteCount = byteArray.length; byteIndex = 0; List codePoints = new ArrayList(); int tmp; - while ((tmp = decodeSymbol()) != -1) { + while ((tmp = decodeSymbol(strict)) != -1) { codePoints.add(tmp); } return ucs2encode(listToArray(codePoints)); @@ -54,7 +66,7 @@ public final class UTF8 { return output; } - private static String encodeCodePoint(int codePoint) throws UTF8Exception { + private static String encodeCodePoint(int codePoint, boolean strict) throws UTF8Exception { StringBuilder symbol = new StringBuilder(); if ((codePoint & 0xFFFFFF80) == 0) { return symbol.append(Character.toChars(codePoint)).toString(); @@ -62,7 +74,9 @@ public final class UTF8 { if ((codePoint & 0xFFFFF800) == 0) { symbol.append(Character.toChars(((codePoint >> 6) & 0x1F) | 0xC0)); } else if ((codePoint & 0xFFFF0000) == 0) { - checkScalarValue(codePoint); + if (!checkScalarValue(codePoint, strict)) { + codePoint = 0xFFFD; + } symbol.append(Character.toChars(((codePoint >> 12) & 0x0F) | 0xE0)); symbol.append(createByte(codePoint, 6)); } else if ((codePoint & 0xFFE00000) == 0) { @@ -78,7 +92,7 @@ public final class UTF8 { return Character.toChars(((codePoint >> shift) & 0x3F) | 0x80); } - private static int decodeSymbol() throws UTF8Exception { + private static int decodeSymbol(boolean strict) throws UTF8Exception { int byte1; int byte2; int byte3; @@ -115,8 +129,7 @@ public final class UTF8 { byte3 = readContinuationByte(); codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; if (codePoint >= 0x0800) { - checkScalarValue(codePoint); - return codePoint; + return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD; } else { throw new UTF8Exception(INVALID_CONTINUATION_BYTE); } @@ -158,13 +171,17 @@ public final class UTF8 { return output.toString(); } - private static void checkScalarValue(int codePoint) throws UTF8Exception { + private static boolean checkScalarValue(int codePoint, boolean strict) throws UTF8Exception { if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { - throw new UTF8Exception( - "Lone surrogate U+" + Integer.toHexString(codePoint).toUpperCase() + - " is not a scalar value" - ); + if (strict) { + throw new UTF8Exception( + "Lone surrogate U+" + Integer.toHexString(codePoint).toUpperCase() + + " is not a scalar value" + ); + } + return false; } + return true; } private static int[] listToArray(List list) { @@ -175,4 +192,8 @@ public final class UTF8 { } return array; } + + public static class Options { + public boolean strict = true; + } } From 1b3c79521038cba39344fe576b81f9935ddf883a Mon Sep 17 00:00:00 2001 From: nkzawa Date: Thu, 13 Jul 2017 12:47:00 +0900 Subject: [PATCH 2/5] update parser to not utf8 encode for string payloads --- .../engineio/client/transports/Polling.java | 14 +- .../client/transports/PollingXHR.java | 48 ++++- .../io/socket/engineio/parser/Parser.java | 174 +++++++++++------- .../io/socket/engineio/parser/ParserTest.java | 64 ++++--- 4 files changed, 197 insertions(+), 103 deletions(-) diff --git a/src/main/java/io/socket/engineio/client/transports/Polling.java b/src/main/java/io/socket/engineio/client/transports/Polling.java index b6d577b..a055357 100644 --- a/src/main/java/io/socket/engineio/client/transports/Polling.java +++ b/src/main/java/io/socket/engineio/client/transports/Polling.java @@ -183,10 +183,16 @@ abstract public class Polling extends Transport { } }; - Parser.encodePayload(packets, new Parser.EncodeCallback() { + Parser.encodePayload(packets, new Parser.EncodeCallback() { @Override - public void call(byte[] data) { - self.doWrite(data, callbackfn); + public void call(Object data) { + if (data instanceof byte[]) { + self.doWrite((byte[])data, callbackfn); + } else if (data instanceof String) { + self.doWrite((String)data, callbackfn); + } else { + logger.warning("Unexpected data: " + data); + } } }); } @@ -220,5 +226,7 @@ abstract public class Polling extends Transport { abstract protected void doWrite(byte[] data, Runnable fn); + abstract protected void doWrite(String data, Runnable fn); + abstract protected void doPoll(); } diff --git a/src/main/java/io/socket/engineio/client/transports/PollingXHR.java b/src/main/java/io/socket/engineio/client/transports/PollingXHR.java index d0e2675..ed118eb 100644 --- a/src/main/java/io/socket/engineio/client/transports/PollingXHR.java +++ b/src/main/java/io/socket/engineio/client/transports/PollingXHR.java @@ -8,6 +8,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; +import java.util.logging.Level; import java.util.logging.Logger; import io.socket.emitter.Emitter; @@ -26,6 +27,8 @@ public class PollingXHR extends Polling { private static final Logger logger = Logger.getLogger(PollingXHR.class.getName()); + private static boolean LOGGABLE_FINE = logger.isLoggable(Level.FINE); + public PollingXHR(Transport.Options opts) { super(opts); } @@ -66,6 +69,15 @@ public class PollingXHR extends Polling { @Override protected void doWrite(byte[] data, final Runnable fn) { + this.doWrite((Object) data, fn); + } + + @Override + protected void doWrite(String data, final Runnable fn) { + this.doWrite((Object) data, fn); + } + + private void doWrite(Object data, final Runnable fn) { Request.Options opts = new Request.Options(); opts.method = "POST"; opts.data = data; @@ -140,13 +152,17 @@ public class PollingXHR extends Polling { public static final String EVENT_ERROR = "error"; public static final String EVENT_REQUEST_HEADERS = "requestHeaders"; public static final String EVENT_RESPONSE_HEADERS = "responseHeaders"; + private static final String BINARY_CONTENT_TYPE = "application/octet-stream"; + private static final String TEXT_CONTENT_TYPE = "text/plain;charset=UTF-8"; + + private static final MediaType BINARY_MEDIA_TYPE = MediaType.parse(BINARY_CONTENT_TYPE); + private static final MediaType TEXT_MEDIA_TYPE = MediaType.parse(TEXT_CONTENT_TYPE); private String method; private String uri; - // data is always a binary - private byte[] data; + private Object data; private Call.Factory callFactory; private Response response; @@ -161,28 +177,42 @@ public class PollingXHR extends Polling { public void create() { final Request self = this; - logger.fine(String.format("xhr open %s: %s", this.method, this.uri)); + if (LOGGABLE_FINE) logger.fine(String.format("xhr open %s: %s", this.method, this.uri)); Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); if ("POST".equals(this.method)) { - headers.put("Content-type", new LinkedList(Collections.singletonList(BINARY_CONTENT_TYPE))); + if (this.data instanceof byte[]) { + headers.put("Content-type", new LinkedList(Collections.singletonList(BINARY_CONTENT_TYPE))); + } else { + headers.put("Content-type", new LinkedList(Collections.singletonList(TEXT_CONTENT_TYPE))); + } } headers.put("Accept", new LinkedList(Collections.singletonList("*/*"))); - self.onRequestHeaders(headers); + this.onRequestHeaders(headers); + + if (LOGGABLE_FINE) { + logger.fine(String.format("sending xhr with url %s | data %s", this.uri, + this.data instanceof byte[] ? Arrays.toString((byte[]) this.data) : this.data)); + } - logger.fine(String.format("sending xhr with url %s | data %s", this.uri, Arrays.toString(this.data))); okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); for (Map.Entry> header : headers.entrySet()) { for (String v : header.getValue()){ requestBuilder.addHeader(header.getKey(), v); } } + RequestBody body = null; + if (this.data instanceof byte[]) { + body = RequestBody.create(BINARY_MEDIA_TYPE, (byte[])this.data); + } else if (this.data instanceof String) { + body = RequestBody.create(TEXT_MEDIA_TYPE, (String)this.data); + } + okhttp3.Request request = requestBuilder .url(HttpUrl.parse(self.uri)) - .method(self.method, (self.data != null) ? - RequestBody.create(MediaType.parse(BINARY_CONTENT_TYPE), self.data) : null) + .method(self.method, body) .build(); requestCall = callFactory.newCall(request); @@ -255,7 +285,7 @@ public class PollingXHR extends Polling { public String uri; public String method; - public byte[] data; + public Object data; public Call.Factory callFactory; } } diff --git a/src/main/java/io/socket/engineio/parser/Parser.java b/src/main/java/io/socket/engineio/parser/Parser.java index c34dce5..fe6c362 100644 --- a/src/main/java/io/socket/engineio/parser/Parser.java +++ b/src/main/java/io/socket/engineio/parser/Parser.java @@ -35,6 +35,11 @@ public class Parser { private static Packet err = new Packet(Packet.ERROR, "parser error"); + private static UTF8.Options utf8Options = new UTF8.Options(); + static { + utf8Options.strict = false; + } + private Parser() {} @@ -55,7 +60,7 @@ public class Parser { String encoded = String.valueOf(packets.get(packet.type)); if (null != packet.data) { - encoded += utf8encode ? UTF8.encode(String.valueOf(packet.data)) : String.valueOf(packet.data); + encoded += utf8encode ? UTF8.encode(String.valueOf(packet.data), utf8Options) : String.valueOf(packet.data); } @SuppressWarnings("unchecked") @@ -89,7 +94,7 @@ public class Parser { if (utf8decode) { try { - data = UTF8.decode(data); + data = UTF8.decode(data, utf8Options); } catch (UTF8Exception e) { return err; } @@ -113,7 +118,40 @@ public class Parser { return new Packet(packetslist.get(type), intArray); } - public static void encodePayload(Packet[] packets, EncodeCallback callback) throws UTF8Exception { + public static void encodePayload(Packet[] packets, EncodeCallback callback) throws UTF8Exception { + for (Packet packet : packets) { + if (packet.data instanceof byte[]) { + @SuppressWarnings("unchecked") + EncodeCallback _callback = (EncodeCallback) callback; + encodePayloadAsBinary(packets, _callback); + return; + } + } + + if (packets.length == 0) { + callback.call("0:"); + return; + } + + final StringBuilder result = new StringBuilder(); + + for (Packet packet : packets) { + encodePacket(packet, false, new EncodeCallback() { + @Override + public void call(Object message) { + result.append(setLengthHeader((String)message)); + } + }); + } + + callback.call(result.toString()); + } + + private static String setLengthHeader(String message) { + return message.length() + ":" + message; + } + + private static void encodePayloadAsBinary(Packet[] packets, EncodeCallback callback) throws UTF8Exception { if (packets.length == 0) { callback.call(new byte[0]); return; @@ -122,30 +160,10 @@ public class Parser { final ArrayList results = new ArrayList(packets.length); for (Packet packet : packets) { - encodePacket(packet, true, new EncodeCallback() { + encodeOneBinaryPacket(packet, new EncodeCallback() { @Override - public void call(Object packet) { - if (packet instanceof String) { - String encodingLength = String.valueOf(((String) packet).length()); - byte[] sizeBuffer = new byte[encodingLength.length() + 2]; - - sizeBuffer[0] = (byte)0; // is a string - for (int i = 0; i < encodingLength.length(); i ++) { - sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i)); - } - sizeBuffer[sizeBuffer.length - 1] = (byte)255; - results.add(Buffer.concat(new byte[][] {sizeBuffer, stringToByteArray((String)packet)})); - return; - } - - String encodingLength = String.valueOf(((byte[])packet).length); - byte[] sizeBuffer = new byte[encodingLength.length() + 2]; - sizeBuffer[0] = (byte)1; // is binary - for (int i = 0; i < encodingLength.length(); i ++) { - sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i)); - } - sizeBuffer[sizeBuffer.length - 1] = (byte)255; - results.add(Buffer.concat(new byte[][] {sizeBuffer, (byte[])packet})); + public void call(byte[] data) { + results.add(data); } }); } @@ -153,6 +171,35 @@ public class Parser { callback.call(Buffer.concat(results.toArray(new byte[results.size()][]))); } + private static void encodeOneBinaryPacket(Packet p, final EncodeCallback doneCallback) throws UTF8Exception { + encodePacket(p, true, new EncodeCallback() { + @Override + public void call(Object packet) { + if (packet instanceof String) { + String encodingLength = String.valueOf(((String) packet).length()); + byte[] sizeBuffer = new byte[encodingLength.length() + 2]; + + sizeBuffer[0] = (byte)0; // is a string + for (int i = 0; i < encodingLength.length(); i ++) { + sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i)); + } + sizeBuffer[sizeBuffer.length - 1] = (byte)255; + doneCallback.call(Buffer.concat(new byte[][] {sizeBuffer, stringToByteArray((String)packet)})); + return; + } + + String encodingLength = String.valueOf(((byte[])packet).length); + byte[] sizeBuffer = new byte[encodingLength.length() + 2]; + sizeBuffer[0] = (byte)1; // is binary + for (int i = 0; i < encodingLength.length(); i ++) { + sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i)); + } + sizeBuffer[sizeBuffer.length - 1] = (byte)255; + doneCallback.call(Buffer.concat(new byte[][] {sizeBuffer, (byte[])packet})); + } + }); + } + public static void decodePayload(String data, DecodePayloadCallback callback) { if (data == null || data.length() == 0) { callback.call(err, 0, 1); @@ -165,37 +212,40 @@ public class Parser { if (':' != chr) { length.append(chr); - } else { - int n; - try { - n = Integer.parseInt(length.toString()); - } catch (NumberFormatException e) { - callback.call(err, 0, 1); - return; - } - - String msg; - try { - msg = data.substring(i + 1, i + 1 + n); - } catch (IndexOutOfBoundsException e) { - callback.call(err, 0, 1); - return; - } - - if (msg.length() != 0) { - Packet packet = decodePacket(msg, true); - if (err.type.equals(packet.type) && err.data.equals(packet.data)) { - callback.call(err, 0, 1); - return; - } - - boolean ret = callback.call(packet, i + n, l); - if (!ret) return; - } - - i += n; - length = new StringBuilder(); + continue; } + + int n; + try { + n = Integer.parseInt(length.toString()); + } catch (NumberFormatException e) { + callback.call(err, 0, 1); + return; + } + + String msg; + try { + msg = data.substring(i + 1, i + 1 + n); + } catch (IndexOutOfBoundsException e) { + callback.call(err, 0, 1); + return; + } + + if (msg.length() != 0) { + Packet packet = decodePacket(msg, false); + if (err.type.equals(packet.type) && err.data.equals(packet.data)) { + callback.call(err, 0, 1); + return; + } + + boolean ret = callback.call(packet, i + n, l); + if (!ret) { + return; + } + } + + i += n; + length = new StringBuilder(); } if (length.length() > 0) { @@ -210,23 +260,17 @@ public class Parser { while (bufferTail.capacity() > 0) { StringBuilder strLen = new StringBuilder(); boolean isString = (bufferTail.get(0) & 0xFF) == 0; - boolean numberTooLong = false; for (int i = 1; ; i++) { int b = bufferTail.get(i) & 0xFF; if (b == 255) break; // supports only integer if (strLen.length() > MAX_INT_CHAR_LENGTH) { - numberTooLong = true; - break; + callback.call(err, 0, 1); + return; } strLen.append(b); } - if (numberTooLong) { - @SuppressWarnings("unchecked") - DecodePayloadCallback tempCallback = callback; - tempCallback.call(err, 0, 1); - return; - } + bufferTail.position(strLen.length() + 1); bufferTail = bufferTail.slice(); diff --git a/src/test/java/io/socket/engineio/parser/ParserTest.java b/src/test/java/io/socket/engineio/parser/ParserTest.java index 86b7c7f..d8e7692 100644 --- a/src/test/java/io/socket/engineio/parser/ParserTest.java +++ b/src/test/java/io/socket/engineio/parser/ParserTest.java @@ -156,6 +156,19 @@ public class ParserTest { }); } + @Test + public void encodingStringMessageWithLoneSurrogatesReplacedByUFFFD() throws UTF8Exception { + String data = "\uDC00\uD834\uDF06\uDC00 \uD800\uD835\uDF07\uD800"; + encodePacket(new Packet(Packet.MESSAGE, data), true, new EncodeCallback() { + @Override + public void call(String encoded) { + Packet p = decodePacket(encoded, true); + assertThat(p.type, is(Packet.MESSAGE)); + assertThat(p.data, is("\uFFFD\uD834\uDF06\uFFFD \uFFFD\uD835\uDF07\uFFFD")); + } + }); + } + @Test public void decodeEmptyPayload() { Packet p = decodePacket((String)null); @@ -186,20 +199,20 @@ public class ParserTest { @Test public void encodePayloads() throws UTF8Exception { - encodePayload(new Packet[]{new Packet(Packet.PING), new Packet(Packet.PONG)}, new EncodeCallback() { + encodePayload(new Packet[]{new Packet(Packet.PING), new Packet(Packet.PONG)}, new EncodeCallback() { @Override - public void call(byte[] data) { - assertThat(data, isA(byte[].class)); + public void call(String data) { + assertThat(data, isA(String.class)); } }); } @Test public void encodeAndDecodePayloads() throws UTF8Exception { - encodePayload(new Packet[] {new Packet(Packet.MESSAGE, "a")}, new EncodeCallback() { + encodePayload(new Packet[] {new Packet(Packet.MESSAGE, "a")}, new EncodeCallback() { @Override - public void call(byte[] data) { - decodePayload(data, new DecodePayloadCallback() { + public void call(String data) { + decodePayload(data, new DecodePayloadCallback() { @Override public boolean call(Packet packet, int index, int total) { boolean isLast = index + 1 == total; @@ -209,10 +222,10 @@ public class ParserTest { }); } }); - encodePayload(new Packet[]{new Packet(Packet.MESSAGE, "a"), new Packet(Packet.PING)}, new EncodeCallback() { + encodePayload(new Packet[]{new Packet(Packet.MESSAGE, "a"), new Packet(Packet.PING)}, new EncodeCallback() { @Override - public void call(byte[] data) { - decodePayload(data, new DecodePayloadCallback() { + public void call(String data) { + decodePayload(data, new DecodePayloadCallback() { @Override public boolean call(Packet packet, int index, int total) { boolean isLast = index + 1 == total; @@ -230,10 +243,10 @@ public class ParserTest { @Test public void encodeAndDecodeEmptyPayloads() throws UTF8Exception { - encodePayload(new Packet[] {}, new EncodeCallback() { + encodePayload(new Packet[] {}, new EncodeCallback() { @Override - public void call(byte[] data) { - decodePayload(data, new DecodePayloadCallback() { + public void call(String data) { + decodePayload(data, new DecodePayloadCallback() { @Override public boolean call(Packet packet, int index, int total) { assertThat(packet.type, is(Packet.OPEN)); @@ -246,6 +259,19 @@ public class ParserTest { }); } + @Test + public void notUTF8EncodeWhenDealingWithStringsOnly() throws UTF8Exception { + encodePayload(new Packet[] { + new Packet(Packet.MESSAGE, "€€€"), + new Packet(Packet.MESSAGE, "α") + }, new EncodeCallback() { + @Override + public void call(String data) { + assertThat(data, is("4:4€€€2:4α")); + } + }); + } + @Test public void decodePayloadBadFormat() { decodePayload("1!", new DecodePayloadCallback() { @@ -328,20 +354,6 @@ public class ParserTest { }); } - @Test - public void decodePayloadInvalidUTF8() { - decodePayload("2:4\uffff", new DecodePayloadCallback() { - @Override - public boolean call(Packet packet, int index, int total) { - boolean isLast = index + 1 == total; - assertThat(packet.type, is(Packet.ERROR)); - assertThat(packet.data, is(ERROR_DATA)); - assertThat(isLast, is(true)); - return true; - } - }); - } - @Test public void encodeBinaryMessage() throws UTF8Exception { final byte[] data = new byte[5]; From 46de5813ca9858d90af1525b409d332211551f13 Mon Sep 17 00:00:00 2001 From: nkzawa Date: Thu, 13 Jul 2017 12:47:48 +0900 Subject: [PATCH 3/5] run tests against engine.io 3.1.0 --- src/test/resources/package-lock.json | 212 ++++++++++++++------------- src/test/resources/package.json | 2 +- src/test/resources/server.js | 5 +- 3 files changed, 114 insertions(+), 105 deletions(-) diff --git a/src/test/resources/package-lock.json b/src/test/resources/package-lock.json index 9289260..1cea691 100644 --- a/src/test/resources/package-lock.json +++ b/src/test/resources/package-lock.json @@ -2,10 +2,34 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "requires": { + "mime-types": "2.1.15", + "negotiator": "0.6.1" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, "arraybuffer.slice": { "version": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=" }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, "blob": { "version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" @@ -15,122 +39,104 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, "engine.io": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.4.tgz", - "integrity": "sha1-d7zhK4Dl1gQpM3/sOw2vaR68kAM=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.0.tgz", + "integrity": "sha1-XKQ4486f28kVxKIcjdnhJmcG5X4=", "requires": { "accepts": "1.3.3", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.4" + "debug": "2.6.8", + "engine.io-parser": "2.1.1", + "uws": "0.14.5", + "ws": "2.3.1" + } + }, + "engine.io-parser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.1.tgz", + "integrity": "sha1-4Ps/DgRi9/WLt3waUun1p+JuRmg=", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", + "base64-arraybuffer": "0.1.5", + "blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "has-binary2": "1.0.2" + } + }, + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", + "requires": { + "isarray": "2.0.1" }, "dependencies": { - "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "requires": { - "mime-types": "2.1.15", - "negotiator": "0.6.1" - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" - }, - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "requires": { - "ms": "0.7.2" - } - }, - "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", - "base64-arraybuffer": "0.1.5", - "blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" - } - }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - } - }, - "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" - }, - "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", - "requires": { - "mime-db": "1.27.0" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "ws": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.4.tgz", - "integrity": "sha1-V/QNA2gy5fUFVmKjl8Tedu1mv2E=", - "requires": { - "options": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "ultron": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz" - } + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" } } }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" }, - "options": { - "version": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "requires": { + "mime-db": "1.27.0" + } }, - "ultron": { - "version": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=" + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "uws": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", + "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", + "optional": true + }, + "ws": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=", + "requires": { + "safe-buffer": "5.0.1", + "ultron": "1.1.0" + }, + "dependencies": { + "ultron": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", + "integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ=" + } + } } } } diff --git a/src/test/resources/package.json b/src/test/resources/package.json index 68be2fb..f7c5917 100644 --- a/src/test/resources/package.json +++ b/src/test/resources/package.json @@ -1,6 +1,6 @@ { "private": true, "dependencies": { - "engine.io": "1.8.4" + "engine.io": "3.1.0" } } diff --git a/src/test/resources/server.js b/src/test/resources/server.js index ef43dee..31a5a70 100644 --- a/src/test/resources/server.js +++ b/src/test/resources/server.js @@ -11,7 +11,10 @@ if (process.env.SSL) { http = require('http').createServer(); } -var server = engine.attach(http, {pingInterval: 500}); +var server = engine.attach(http, { + pingInterval: 500, + wsEngine: 'ws' +}); var port = process.env.PORT || 3000 http.listen(port, function() { From c8867048dd6f85ec04e2e6d08de4593a6b10dcbc Mon Sep 17 00:00:00 2001 From: nkzawa Date: Thu, 13 Jul 2017 12:51:29 +0900 Subject: [PATCH 4/5] add the transportOptions option --- .../io/socket/engineio/client/Socket.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/socket/engineio/client/Socket.java b/src/main/java/io/socket/engineio/client/Socket.java index 796b88f..60b914e 100644 --- a/src/main/java/io/socket/engineio/client/Socket.java +++ b/src/main/java/io/socket/engineio/client/Socket.java @@ -121,6 +121,7 @@ public class Socket extends Emitter { private String path; private String timestampParam; private List transports; + private Map transportOptions; private List upgrades; private Map query; /*package*/ LinkedList writeBuffer = new LinkedList(); @@ -202,6 +203,8 @@ public class Socket extends Emitter { this.timestampRequests = opts.timestampRequests; this.transports = new ArrayList(Arrays.asList(opts.transports != null ? opts.transports : new String[]{Polling.NAME, WebSocket.NAME})); + this.transportOptions = opts.transportOptions != null ? + opts.transportOptions : new HashMap(); this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843; this.rememberUpgrade = opts.rememberUpgrade; this.callFactory = opts.callFactory != null ? opts.callFactory : defaultCallFactory; @@ -272,18 +275,22 @@ public class Socket extends Emitter { query.put("sid", this.id); } + // per-transport options + Transport.Options options = this.transportOptions.get(name); + Transport.Options opts = new Transport.Options(); - opts.hostname = this.hostname; - opts.port = this.port; - opts.secure = this.secure; - opts.path = this.path; opts.query = query; - opts.timestampRequests = this.timestampRequests; - opts.timestampParam = this.timestampParam; - opts.policyPort = this.policyPort; opts.socket = this; - opts.callFactory = this.callFactory; - opts.webSocketFactory = this.webSocketFactory; + + opts.hostname = options != null ? options.hostname : this.hostname; + opts.port = options != null ? options.port : this.port; + opts.secure = options != null ? options.secure : this.secure; + opts.path = options != null ? options.path : this.path; + opts.timestampRequests = options != null ? options.timestampRequests : this.timestampRequests; + opts.timestampParam = options != null ? options.timestampParam : this.timestampParam; + opts.policyPort = options != null ? options.policyPort : this.policyPort; + opts.callFactory = options != null ? options.callFactory : this.callFactory; + opts.webSocketFactory = options != null ? options.webSocketFactory : this.webSocketFactory; Transport transport; if (WebSocket.NAME.equals(name)) { @@ -866,7 +873,7 @@ public class Socket extends Emitter { public boolean rememberUpgrade; public String host; public String query; - + public Map transportOptions; private static Options fromURI(URI uri, Options opts) { if (opts == null) { From ce1c29daeb2c6dcf48dd205f6334a6df26a0d2cc Mon Sep 17 00:00:00 2001 From: nkzawa Date: Thu, 13 Jul 2017 15:41:49 +0900 Subject: [PATCH 5/5] update travis setting --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index ab29bcc..84c2bc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: java +sudo: false install: mvn install -DskipTests=true -Dgpg.skip=true jdk: - openjdk7 - oraclejdk8 +dist: trusty