Merge pull request #93 from socketio/fix/compatible-v3
Update to make compatible with engine.io v3
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
language: java
|
language: java
|
||||||
|
sudo: false
|
||||||
install: mvn install -DskipTests=true -Dgpg.skip=true
|
install: mvn install -DskipTests=true -Dgpg.skip=true
|
||||||
jdk:
|
jdk:
|
||||||
- openjdk7
|
- openjdk7
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
dist: trusty
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ public class Socket extends Emitter {
|
|||||||
private String path;
|
private String path;
|
||||||
private String timestampParam;
|
private String timestampParam;
|
||||||
private List<String> transports;
|
private List<String> transports;
|
||||||
|
private Map<String, Transport.Options> transportOptions;
|
||||||
private List<String> upgrades;
|
private List<String> upgrades;
|
||||||
private Map<String, String> query;
|
private Map<String, String> query;
|
||||||
/*package*/ LinkedList<Packet> writeBuffer = new LinkedList<Packet>();
|
/*package*/ LinkedList<Packet> writeBuffer = new LinkedList<Packet>();
|
||||||
@@ -202,6 +203,8 @@ public class Socket extends Emitter {
|
|||||||
this.timestampRequests = opts.timestampRequests;
|
this.timestampRequests = opts.timestampRequests;
|
||||||
this.transports = new ArrayList<String>(Arrays.asList(opts.transports != null ?
|
this.transports = new ArrayList<String>(Arrays.asList(opts.transports != null ?
|
||||||
opts.transports : new String[]{Polling.NAME, WebSocket.NAME}));
|
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.policyPort = opts.policyPort != 0 ? opts.policyPort : 843;
|
||||||
this.rememberUpgrade = opts.rememberUpgrade;
|
this.rememberUpgrade = opts.rememberUpgrade;
|
||||||
this.callFactory = opts.callFactory != null ? opts.callFactory : defaultCallFactory;
|
this.callFactory = opts.callFactory != null ? opts.callFactory : defaultCallFactory;
|
||||||
@@ -272,18 +275,22 @@ public class Socket extends Emitter {
|
|||||||
query.put("sid", this.id);
|
query.put("sid", this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// per-transport options
|
||||||
|
Transport.Options options = this.transportOptions.get(name);
|
||||||
|
|
||||||
Transport.Options opts = new Transport.Options();
|
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.query = query;
|
||||||
opts.timestampRequests = this.timestampRequests;
|
|
||||||
opts.timestampParam = this.timestampParam;
|
|
||||||
opts.policyPort = this.policyPort;
|
|
||||||
opts.socket = this;
|
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;
|
Transport transport;
|
||||||
if (WebSocket.NAME.equals(name)) {
|
if (WebSocket.NAME.equals(name)) {
|
||||||
@@ -866,7 +873,7 @@ public class Socket extends Emitter {
|
|||||||
public boolean rememberUpgrade;
|
public boolean rememberUpgrade;
|
||||||
public String host;
|
public String host;
|
||||||
public String query;
|
public String query;
|
||||||
|
public Map<String, Transport.Options> transportOptions;
|
||||||
|
|
||||||
private static Options fromURI(URI uri, Options opts) {
|
private static Options fromURI(URI uri, Options opts) {
|
||||||
if (opts == null) {
|
if (opts == null) {
|
||||||
|
|||||||
@@ -183,10 +183,16 @@ abstract public class Polling extends Transport {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.encodePayload(packets, new Parser.EncodeCallback<byte[]>() {
|
Parser.encodePayload(packets, new Parser.EncodeCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void call(byte[] data) {
|
public void call(Object data) {
|
||||||
self.doWrite(data, callbackfn);
|
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(byte[] data, Runnable fn);
|
||||||
|
|
||||||
|
abstract protected void doWrite(String data, Runnable fn);
|
||||||
|
|
||||||
abstract protected void doPoll();
|
abstract protected void doPoll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.socket.emitter.Emitter;
|
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 final Logger logger = Logger.getLogger(PollingXHR.class.getName());
|
||||||
|
|
||||||
|
private static boolean LOGGABLE_FINE = logger.isLoggable(Level.FINE);
|
||||||
|
|
||||||
public PollingXHR(Transport.Options opts) {
|
public PollingXHR(Transport.Options opts) {
|
||||||
super(opts);
|
super(opts);
|
||||||
}
|
}
|
||||||
@@ -66,6 +69,15 @@ public class PollingXHR extends Polling {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doWrite(byte[] data, final Runnable fn) {
|
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();
|
Request.Options opts = new Request.Options();
|
||||||
opts.method = "POST";
|
opts.method = "POST";
|
||||||
opts.data = data;
|
opts.data = data;
|
||||||
@@ -140,13 +152,17 @@ public class PollingXHR extends Polling {
|
|||||||
public static final String EVENT_ERROR = "error";
|
public static final String EVENT_ERROR = "error";
|
||||||
public static final String EVENT_REQUEST_HEADERS = "requestHeaders";
|
public static final String EVENT_REQUEST_HEADERS = "requestHeaders";
|
||||||
public static final String EVENT_RESPONSE_HEADERS = "responseHeaders";
|
public static final String EVENT_RESPONSE_HEADERS = "responseHeaders";
|
||||||
|
|
||||||
private static final String BINARY_CONTENT_TYPE = "application/octet-stream";
|
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 method;
|
||||||
private String uri;
|
private String uri;
|
||||||
|
|
||||||
// data is always a binary
|
private Object data;
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
private Call.Factory callFactory;
|
private Call.Factory callFactory;
|
||||||
private Response response;
|
private Response response;
|
||||||
@@ -161,28 +177,42 @@ public class PollingXHR extends Polling {
|
|||||||
|
|
||||||
public void create() {
|
public void create() {
|
||||||
final Request self = this;
|
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);
|
Map<String, List<String>> headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
if ("POST".equals(this.method)) {
|
if ("POST".equals(this.method)) {
|
||||||
|
if (this.data instanceof byte[]) {
|
||||||
headers.put("Content-type", new LinkedList<String>(Collections.singletonList(BINARY_CONTENT_TYPE)));
|
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("*/*")));
|
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();
|
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
|
||||||
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
||||||
for (String v : header.getValue()){
|
for (String v : header.getValue()){
|
||||||
requestBuilder.addHeader(header.getKey(), v);
|
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
|
okhttp3.Request request = requestBuilder
|
||||||
.url(HttpUrl.parse(self.uri))
|
.url(HttpUrl.parse(self.uri))
|
||||||
.method(self.method, (self.data != null) ?
|
.method(self.method, body)
|
||||||
RequestBody.create(MediaType.parse(BINARY_CONTENT_TYPE), self.data) : null)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
requestCall = callFactory.newCall(request);
|
requestCall = callFactory.newCall(request);
|
||||||
@@ -255,7 +285,7 @@ public class PollingXHR extends Polling {
|
|||||||
|
|
||||||
public String uri;
|
public String uri;
|
||||||
public String method;
|
public String method;
|
||||||
public byte[] data;
|
public Object data;
|
||||||
public Call.Factory callFactory;
|
public Call.Factory callFactory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ public class Parser {
|
|||||||
|
|
||||||
private static Packet<String> err = new Packet<String>(Packet.ERROR, "parser error");
|
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() {}
|
private Parser() {}
|
||||||
|
|
||||||
@@ -55,7 +60,7 @@ public class Parser {
|
|||||||
String encoded = String.valueOf(packets.get(packet.type));
|
String encoded = String.valueOf(packets.get(packet.type));
|
||||||
|
|
||||||
if (null != packet.data) {
|
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")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -89,7 +94,7 @@ public class Parser {
|
|||||||
|
|
||||||
if (utf8decode) {
|
if (utf8decode) {
|
||||||
try {
|
try {
|
||||||
data = UTF8.decode(data);
|
data = UTF8.decode(data, utf8Options);
|
||||||
} catch (UTF8Exception e) {
|
} catch (UTF8Exception e) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -113,7 +118,40 @@ public class Parser {
|
|||||||
return new Packet<byte[]>(packetslist.get(type), intArray);
|
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) {
|
if (packets.length == 0) {
|
||||||
callback.call(new byte[0]);
|
callback.call(new byte[0]);
|
||||||
return;
|
return;
|
||||||
@@ -122,7 +160,19 @@ public class Parser {
|
|||||||
final ArrayList<byte[]> results = new ArrayList<byte[]>(packets.length);
|
final ArrayList<byte[]> results = new ArrayList<byte[]>(packets.length);
|
||||||
|
|
||||||
for (Packet packet : packets) {
|
for (Packet packet : packets) {
|
||||||
encodePacket(packet, true, new EncodeCallback() {
|
encodeOneBinaryPacket(packet, new EncodeCallback<byte[]>() {
|
||||||
|
@Override
|
||||||
|
public void call(byte[] data) {
|
||||||
|
results.add(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public void call(Object packet) {
|
public void call(Object packet) {
|
||||||
if (packet instanceof String) {
|
if (packet instanceof String) {
|
||||||
@@ -134,7 +184,7 @@ public class Parser {
|
|||||||
sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
|
sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
|
||||||
}
|
}
|
||||||
sizeBuffer[sizeBuffer.length - 1] = (byte)255;
|
sizeBuffer[sizeBuffer.length - 1] = (byte)255;
|
||||||
results.add(Buffer.concat(new byte[][] {sizeBuffer, stringToByteArray((String)packet)}));
|
doneCallback.call(Buffer.concat(new byte[][] {sizeBuffer, stringToByteArray((String)packet)}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,14 +195,11 @@ public class Parser {
|
|||||||
sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
|
sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
|
||||||
}
|
}
|
||||||
sizeBuffer[sizeBuffer.length - 1] = (byte)255;
|
sizeBuffer[sizeBuffer.length - 1] = (byte)255;
|
||||||
results.add(Buffer.concat(new byte[][] {sizeBuffer, (byte[])packet}));
|
doneCallback.call(Buffer.concat(new byte[][] {sizeBuffer, (byte[])packet}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.call(Buffer.concat(results.toArray(new byte[results.size()][])));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void decodePayload(String data, DecodePayloadCallback<String> callback) {
|
public static void decodePayload(String data, DecodePayloadCallback<String> callback) {
|
||||||
if (data == null || data.length() == 0) {
|
if (data == null || data.length() == 0) {
|
||||||
callback.call(err, 0, 1);
|
callback.call(err, 0, 1);
|
||||||
@@ -165,7 +212,9 @@ public class Parser {
|
|||||||
|
|
||||||
if (':' != chr) {
|
if (':' != chr) {
|
||||||
length.append(chr);
|
length.append(chr);
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
try {
|
try {
|
||||||
n = Integer.parseInt(length.toString());
|
n = Integer.parseInt(length.toString());
|
||||||
@@ -183,20 +232,21 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg.length() != 0) {
|
if (msg.length() != 0) {
|
||||||
Packet<String> packet = decodePacket(msg, true);
|
Packet<String> packet = decodePacket(msg, false);
|
||||||
if (err.type.equals(packet.type) && err.data.equals(packet.data)) {
|
if (err.type.equals(packet.type) && err.data.equals(packet.data)) {
|
||||||
callback.call(err, 0, 1);
|
callback.call(err, 0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ret = callback.call(packet, i + n, l);
|
boolean ret = callback.call(packet, i + n, l);
|
||||||
if (!ret) return;
|
if (!ret) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += n;
|
i += n;
|
||||||
length = new StringBuilder();
|
length = new StringBuilder();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (length.length() > 0) {
|
if (length.length() > 0) {
|
||||||
callback.call(err, 0, 1);
|
callback.call(err, 0, 1);
|
||||||
@@ -210,23 +260,17 @@ public class Parser {
|
|||||||
while (bufferTail.capacity() > 0) {
|
while (bufferTail.capacity() > 0) {
|
||||||
StringBuilder strLen = new StringBuilder();
|
StringBuilder strLen = new StringBuilder();
|
||||||
boolean isString = (bufferTail.get(0) & 0xFF) == 0;
|
boolean isString = (bufferTail.get(0) & 0xFF) == 0;
|
||||||
boolean numberTooLong = false;
|
|
||||||
for (int i = 1; ; i++) {
|
for (int i = 1; ; i++) {
|
||||||
int b = bufferTail.get(i) & 0xFF;
|
int b = bufferTail.get(i) & 0xFF;
|
||||||
if (b == 255) break;
|
if (b == 255) break;
|
||||||
// supports only integer
|
// supports only integer
|
||||||
if (strLen.length() > MAX_INT_CHAR_LENGTH) {
|
if (strLen.length() > MAX_INT_CHAR_LENGTH) {
|
||||||
numberTooLong = true;
|
callback.call(err, 0, 1);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
strLen.append(b);
|
strLen.append(b);
|
||||||
}
|
}
|
||||||
if (numberTooLong) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
DecodePayloadCallback<String> tempCallback = callback;
|
|
||||||
tempCallback.call(err, 0, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bufferTail.position(strLen.length() + 1);
|
bufferTail.position(strLen.length() + 1);
|
||||||
bufferTail = bufferTail.slice();
|
bufferTail = bufferTail.slice();
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ public final class UTF8 {
|
|||||||
private UTF8 () {}
|
private UTF8 () {}
|
||||||
|
|
||||||
public static String encode(String string) throws UTF8Exception {
|
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[] codePoints = ucs2decode(string);
|
||||||
int length = codePoints.length;
|
int length = codePoints.length;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
@@ -25,18 +31,24 @@ public final class UTF8 {
|
|||||||
StringBuilder byteString = new StringBuilder();
|
StringBuilder byteString = new StringBuilder();
|
||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
codePoint = codePoints[index];
|
codePoint = codePoints[index];
|
||||||
byteString.append(encodeCodePoint(codePoint));
|
byteString.append(encodeCodePoint(codePoint, strict));
|
||||||
}
|
}
|
||||||
return byteString.toString();
|
return byteString.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String decode(String byteString) throws UTF8Exception {
|
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);
|
byteArray = ucs2decode(byteString);
|
||||||
byteCount = byteArray.length;
|
byteCount = byteArray.length;
|
||||||
byteIndex = 0;
|
byteIndex = 0;
|
||||||
List<Integer> codePoints = new ArrayList<Integer>();
|
List<Integer> codePoints = new ArrayList<Integer>();
|
||||||
int tmp;
|
int tmp;
|
||||||
while ((tmp = decodeSymbol()) != -1) {
|
while ((tmp = decodeSymbol(strict)) != -1) {
|
||||||
codePoints.add(tmp);
|
codePoints.add(tmp);
|
||||||
}
|
}
|
||||||
return ucs2encode(listToArray(codePoints));
|
return ucs2encode(listToArray(codePoints));
|
||||||
@@ -54,7 +66,7 @@ public final class UTF8 {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String encodeCodePoint(int codePoint) throws UTF8Exception {
|
private static String encodeCodePoint(int codePoint, boolean strict) throws UTF8Exception {
|
||||||
StringBuilder symbol = new StringBuilder();
|
StringBuilder symbol = new StringBuilder();
|
||||||
if ((codePoint & 0xFFFFFF80) == 0) {
|
if ((codePoint & 0xFFFFFF80) == 0) {
|
||||||
return symbol.append(Character.toChars(codePoint)).toString();
|
return symbol.append(Character.toChars(codePoint)).toString();
|
||||||
@@ -62,7 +74,9 @@ public final class UTF8 {
|
|||||||
if ((codePoint & 0xFFFFF800) == 0) {
|
if ((codePoint & 0xFFFFF800) == 0) {
|
||||||
symbol.append(Character.toChars(((codePoint >> 6) & 0x1F) | 0xC0));
|
symbol.append(Character.toChars(((codePoint >> 6) & 0x1F) | 0xC0));
|
||||||
} else if ((codePoint & 0xFFFF0000) == 0) {
|
} else if ((codePoint & 0xFFFF0000) == 0) {
|
||||||
checkScalarValue(codePoint);
|
if (!checkScalarValue(codePoint, strict)) {
|
||||||
|
codePoint = 0xFFFD;
|
||||||
|
}
|
||||||
symbol.append(Character.toChars(((codePoint >> 12) & 0x0F) | 0xE0));
|
symbol.append(Character.toChars(((codePoint >> 12) & 0x0F) | 0xE0));
|
||||||
symbol.append(createByte(codePoint, 6));
|
symbol.append(createByte(codePoint, 6));
|
||||||
} else if ((codePoint & 0xFFE00000) == 0) {
|
} else if ((codePoint & 0xFFE00000) == 0) {
|
||||||
@@ -78,7 +92,7 @@ public final class UTF8 {
|
|||||||
return Character.toChars(((codePoint >> shift) & 0x3F) | 0x80);
|
return Character.toChars(((codePoint >> shift) & 0x3F) | 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int decodeSymbol() throws UTF8Exception {
|
private static int decodeSymbol(boolean strict) throws UTF8Exception {
|
||||||
int byte1;
|
int byte1;
|
||||||
int byte2;
|
int byte2;
|
||||||
int byte3;
|
int byte3;
|
||||||
@@ -115,8 +129,7 @@ public final class UTF8 {
|
|||||||
byte3 = readContinuationByte();
|
byte3 = readContinuationByte();
|
||||||
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
||||||
if (codePoint >= 0x0800) {
|
if (codePoint >= 0x0800) {
|
||||||
checkScalarValue(codePoint);
|
return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
|
||||||
return codePoint;
|
|
||||||
} else {
|
} else {
|
||||||
throw new UTF8Exception(INVALID_CONTINUATION_BYTE);
|
throw new UTF8Exception(INVALID_CONTINUATION_BYTE);
|
||||||
}
|
}
|
||||||
@@ -158,13 +171,17 @@ public final class UTF8 {
|
|||||||
return output.toString();
|
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) {
|
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
|
||||||
|
if (strict) {
|
||||||
throw new UTF8Exception(
|
throw new UTF8Exception(
|
||||||
"Lone surrogate U+" + Integer.toHexString(codePoint).toUpperCase() +
|
"Lone surrogate U+" + Integer.toHexString(codePoint).toUpperCase() +
|
||||||
" is not a scalar value"
|
" is not a scalar value"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] listToArray(List<Integer> list) {
|
private static int[] listToArray(List<Integer> list) {
|
||||||
@@ -175,4 +192,8 @@ public final class UTF8 {
|
|||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Options {
|
||||||
|
public boolean strict = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
@Test
|
||||||
public void decodeEmptyPayload() {
|
public void decodeEmptyPayload() {
|
||||||
Packet<String> p = decodePacket((String)null);
|
Packet<String> p = decodePacket((String)null);
|
||||||
@@ -186,20 +199,20 @@ public class ParserTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encodePayloads() throws UTF8Exception {
|
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
|
@Override
|
||||||
public void call(byte[] data) {
|
public void call(String data) {
|
||||||
assertThat(data, isA(byte[].class));
|
assertThat(data, isA(String.class));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encodeAndDecodePayloads() throws UTF8Exception {
|
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
|
@Override
|
||||||
public void call(byte[] data) {
|
public void call(String data) {
|
||||||
decodePayload(data, new DecodePayloadCallback() {
|
decodePayload(data, new DecodePayloadCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean call(Packet packet, int index, int total) {
|
public boolean call(Packet packet, int index, int total) {
|
||||||
boolean isLast = index + 1 == 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
|
@Override
|
||||||
public void call(byte[] data) {
|
public void call(String data) {
|
||||||
decodePayload(data, new DecodePayloadCallback() {
|
decodePayload(data, new DecodePayloadCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean call(Packet packet, int index, int total) {
|
public boolean call(Packet packet, int index, int total) {
|
||||||
boolean isLast = index + 1 == total;
|
boolean isLast = index + 1 == total;
|
||||||
@@ -230,10 +243,10 @@ public class ParserTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encodeAndDecodeEmptyPayloads() throws UTF8Exception {
|
public void encodeAndDecodeEmptyPayloads() throws UTF8Exception {
|
||||||
encodePayload(new Packet[] {}, new EncodeCallback<byte[]>() {
|
encodePayload(new Packet[] {}, new EncodeCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void call(byte[] data) {
|
public void call(String data) {
|
||||||
decodePayload(data, new DecodePayloadCallback() {
|
decodePayload(data, new DecodePayloadCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean call(Packet packet, int index, int total) {
|
public boolean call(Packet packet, int index, int total) {
|
||||||
assertThat(packet.type, is(Packet.OPEN));
|
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
|
@Test
|
||||||
public void decodePayloadBadFormat() {
|
public void decodePayloadBadFormat() {
|
||||||
decodePayload("1!", new DecodePayloadCallback<String>() {
|
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
|
@Test
|
||||||
public void encodeBinaryMessage() throws UTF8Exception {
|
public void encodeBinaryMessage() throws UTF8Exception {
|
||||||
final byte[] data = new byte[5];
|
final byte[] data = new byte[5];
|
||||||
|
|||||||
138
src/test/resources/package-lock.json
generated
138
src/test/resources/package-lock.json
generated
@@ -1,32 +1,6 @@
|
|||||||
{
|
{
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"dependencies": {
|
|
||||||
"arraybuffer.slice": {
|
|
||||||
"version": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
|
|
||||||
"integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco="
|
|
||||||
},
|
|
||||||
"blob": {
|
|
||||||
"version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
|
|
||||||
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
|
|
||||||
},
|
|
||||||
"cookie": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
|
||||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
|
||||||
},
|
|
||||||
"engine.io": {
|
|
||||||
"version": "1.8.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.4.tgz",
|
|
||||||
"integrity": "sha1-d7zhK4Dl1gQpM3/sOw2vaR68kAM=",
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
@@ -42,6 +16,10 @@
|
|||||||
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
|
||||||
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
|
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
|
||||||
},
|
},
|
||||||
|
"arraybuffer.slice": {
|
||||||
|
"version": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
|
||||||
|
"integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco="
|
||||||
|
},
|
||||||
"base64-arraybuffer": {
|
"base64-arraybuffer": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
||||||
@@ -52,33 +30,62 @@
|
|||||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
|
||||||
"integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
|
"integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
|
||||||
},
|
},
|
||||||
|
"blob": {
|
||||||
|
"version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
|
||||||
|
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
|
||||||
|
},
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||||
|
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.3.3",
|
"version": "2.6.8",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
|
||||||
"integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
|
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "0.7.2"
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io": {
|
||||||
|
"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.6.8",
|
||||||
|
"engine.io-parser": "2.1.1",
|
||||||
|
"uws": "0.14.5",
|
||||||
|
"ws": "2.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"engine.io-parser": {
|
"engine.io-parser": {
|
||||||
"version": "1.3.2",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.1.tgz",
|
||||||
"integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
|
"integrity": "sha1-4Ps/DgRi9/WLt3waUun1p+JuRmg=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"after": "0.8.2",
|
"after": "0.8.2",
|
||||||
"arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
|
"arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
|
||||||
"base64-arraybuffer": "0.1.5",
|
"base64-arraybuffer": "0.1.5",
|
||||||
"blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
|
"blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
|
||||||
"has-binary": "0.1.7",
|
"has-binary2": "1.0.2"
|
||||||
"wtf-8": "1.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has-binary": {
|
"has-binary2": {
|
||||||
"version": "0.1.7",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz",
|
||||||
"integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=",
|
"integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
|
"isarray": "2.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
@@ -95,42 +102,41 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "0.7.2",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
},
|
},
|
||||||
"negotiator": {
|
"negotiator": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
||||||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
|
"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": {
|
"ws": {
|
||||||
"version": "1.1.4",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz",
|
||||||
"integrity": "sha1-V/QNA2gy5fUFVmKjl8Tedu1mv2E=",
|
"integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"options": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
|
"safe-buffer": "5.0.1",
|
||||||
"ultron": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
"ultron": "1.1.0"
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isarray": {
|
|
||||||
"version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"version": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
|
|
||||||
"integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8="
|
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
"ultron": {
|
"ultron": {
|
||||||
"version": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
|
"version": "1.1.0",
|
||||||
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
|
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz",
|
||||||
},
|
"integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ="
|
||||||
"wtf-8": {
|
}
|
||||||
"version": "1.0.0",
|
}
|
||||||
"resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"engine.io": "1.8.4"
|
"engine.io": "3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ if (process.env.SSL) {
|
|||||||
http = require('http').createServer();
|
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
|
var port = process.env.PORT || 3000
|
||||||
http.listen(port, function() {
|
http.listen(port, function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user