Merge pull request #93 from socketio/fix/compatible-v3

Update to make compatible with engine.io v3
This commit is contained in:
Naoyuki Kanezawa
2017-07-14 13:39:27 +09:00
committed by GitHub
10 changed files with 363 additions and 230 deletions

View File

@@ -1,5 +1,7 @@
language: java
sudo: false
install: mvn install -DskipTests=true -Dgpg.skip=true
jdk:
- openjdk7
- oraclejdk8
dist: trusty

View File

@@ -121,6 +121,7 @@ public class Socket extends Emitter {
private String path;
private String timestampParam;
private List<String> transports;
private Map<String, Transport.Options> transportOptions;
private List<String> upgrades;
private Map<String, String> query;
/*package*/ LinkedList<Packet> writeBuffer = new LinkedList<Packet>();
@@ -202,6 +203,8 @@ public class Socket extends Emitter {
this.timestampRequests = opts.timestampRequests;
this.transports = new ArrayList<String>(Arrays.asList(opts.transports != null ?
opts.transports : new String[]{Polling.NAME, WebSocket.NAME}));
this.transportOptions = opts.transportOptions != null ?
opts.transportOptions : new HashMap<String, Transport.Options>();
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<String, Transport.Options> transportOptions;
private static Options fromURI(URI uri, Options opts) {
if (opts == null) {

View File

@@ -183,10 +183,16 @@ abstract public class Polling extends Transport {
}
};
Parser.encodePayload(packets, new Parser.EncodeCallback<byte[]>() {
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();
}

View File

@@ -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<String, List<String>> headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
if ("POST".equals(this.method)) {
headers.put("Content-type", new LinkedList<String>(Collections.singletonList(BINARY_CONTENT_TYPE)));
if (this.data instanceof byte[]) {
headers.put("Content-type", new LinkedList<String>(Collections.singletonList(BINARY_CONTENT_TYPE)));
} else {
headers.put("Content-type", new LinkedList<String>(Collections.singletonList(TEXT_CONTENT_TYPE)));
}
}
headers.put("Accept", new LinkedList<String>(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<String, List<String>> 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;
}
}

View File

@@ -35,6 +35,11 @@ public class Parser {
private static Packet<String> err = new Packet<String>(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<byte[]>(packetslist.get(type), intArray);
}
public static void encodePayload(Packet[] packets, EncodeCallback<byte[]> 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<byte[]> _callback = (EncodeCallback<byte[]>) 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<byte[]> callback) throws UTF8Exception {
if (packets.length == 0) {
callback.call(new byte[0]);
return;
@@ -122,30 +160,10 @@ public class Parser {
final ArrayList<byte[]> results = new ArrayList<byte[]>(packets.length);
for (Packet packet : packets) {
encodePacket(packet, true, new EncodeCallback() {
encodeOneBinaryPacket(packet, new EncodeCallback<byte[]>() {
@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<byte[]> 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<String> 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<String> 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<String> 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<String> tempCallback = callback;
tempCallback.call(err, 0, 1);
return;
}
bufferTail.position(strLen.length() + 1);
bufferTail = bufferTail.slice();

View File

@@ -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<Integer> codePoints = new ArrayList<Integer>();
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<Integer> list) {
@@ -175,4 +192,8 @@ public final class UTF8 {
}
return array;
}
public static class Options {
public boolean strict = true;
}
}

View File

@@ -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<String>(Packet.MESSAGE, data), true, new EncodeCallback<String>() {
@Override
public void call(String encoded) {
Packet<String> 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<String> 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<byte[]>() {
encodePayload(new Packet[]{new Packet(Packet.PING), new Packet(Packet.PONG)}, new EncodeCallback<String>() {
@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<String>(Packet.MESSAGE, "a")}, new EncodeCallback<byte[]>() {
encodePayload(new Packet[] {new Packet<String>(Packet.MESSAGE, "a")}, new EncodeCallback<String>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
public void call(String data) {
decodePayload(data, new DecodePayloadCallback<String>() {
@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<String>(Packet.MESSAGE, "a"), new Packet(Packet.PING)}, new EncodeCallback<byte[]>() {
encodePayload(new Packet[]{new Packet<String>(Packet.MESSAGE, "a"), new Packet(Packet.PING)}, new EncodeCallback<String>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
public void call(String data) {
decodePayload(data, new DecodePayloadCallback<String>() {
@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<byte[]>() {
encodePayload(new Packet[] {}, new EncodeCallback<String>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
public void call(String data) {
decodePayload(data, new DecodePayloadCallback<String>() {
@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<String>() {
@Override
public void call(String data) {
assertThat(data, is("4:4€€€2:4α"));
}
});
}
@Test
public void decodePayloadBadFormat() {
decodePayload("1!", new DecodePayloadCallback<String>() {
@@ -328,20 +354,6 @@ public class ParserTest {
});
}
@Test
public void decodePayloadInvalidUTF8() {
decodePayload("2:4\uffff", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet<String> 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];

View File

@@ -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="
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"private": true,
"dependencies": {
"engine.io": "1.8.4"
"engine.io": "3.1.0"
}
}

View File

@@ -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() {