support protocol ver 3 and sending byte data

This commit is contained in:
Naoyuki Kanezawa
2014-03-30 18:46:31 +09:00
parent 808ad8c4f1
commit 19c820334d
9 changed files with 456 additions and 117 deletions

View File

@@ -13,7 +13,10 @@ import com.google.gson.Gson;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
@@ -298,7 +301,7 @@ public abstract class Socket extends Emitter {
if (failed[0]) return;
logger.fine(String.format("probe transport '%s' opened", name));
Packet packet = new Packet(Packet.PING, "probe");
Packet<String> packet = new Packet<String>(Packet.PING, "probe");
transport[0].send(new Packet[] {packet});
transport[0].once(Transport.EVENT_PACKET, new Listener() {
@Override
@@ -395,7 +398,7 @@ public abstract class Socket extends Emitter {
this.emit(EVENT_HEARTBEAT);
if (Packet.OPEN.equals(packet.type)) {
this.onHandshake(gson.fromJson(packet.data, HandshakeData.class));
this.onHandshake(gson.fromJson((String)packet.data, HandshakeData.class));
} else if (Packet.PONG.equals(packet.type)) {
this.setPing();
} else if (Packet.ERROR.equals(packet.type)) {
@@ -406,7 +409,11 @@ public abstract class Socket extends Emitter {
} else if (Packet.MESSAGE.equals(packet.type)) {
this.emit(EVENT_DATA, packet.data);
this.emit(EVENT_MESSAGE, packet.data);
this.onmessage(packet.data);
if (packet.data instanceof String) {
this.onmessage((String)packet.data);
} else if (packet.data instanceof byte[]) {
this.onmessage((byte[])packet.data);
}
}
} else {
logger.fine(String.format("packet received with socket readyState '%s'", this.readyState));
@@ -530,6 +537,14 @@ public abstract class Socket extends Emitter {
this.send(msg, fn);
}
public void write(byte[] msg) {
this.write(msg, null);
}
public void write(byte[] msg, Runnable fn) {
this.send(msg, fn);
}
/**
* Sends a message.
*
@@ -539,6 +554,10 @@ public abstract class Socket extends Emitter {
this.send(msg, null);
}
public void send(byte[] msg) {
this.send(msg, null);
}
/**
* Sends a message.
*
@@ -554,17 +573,35 @@ public abstract class Socket extends Emitter {
});
}
public void send(final byte[] msg, final Runnable fn) {
EventThread.exec(new Runnable() {
@Override
public void run() {
Socket.this.sendPacket(Packet.MESSAGE, msg, fn);
}
});
}
private void sendPacket(String type) {
this.sendPacket(type, null, null);
this.sendPacket(new Packet(type), null);
}
private void sendPacket(String type, String data, Runnable fn) {
Packet<String> packet = new Packet<String>(type, data);
sendPacket(packet, fn);
}
private void sendPacket(String type, byte[] data, Runnable fn) {
Packet<byte[]> packet = new Packet<byte[]>(type, data);
sendPacket(packet, fn);
}
private void sendPacket(Packet packet, Runnable fn) {
if (fn == null) {
// ConcurrentLinkedList does not permit `null`.
fn = noop;
}
Packet packet = new Packet(type, data);
this.emit(EVENT_PACKET_CREATE, packet);
this.writeBuffer.offer(packet);
this.callbackBuffer.offer(fn);
@@ -653,6 +690,8 @@ public abstract class Socket extends Emitter {
return filteredUpgrades;
}
public void onmessage(byte[] data) {};
public abstract void onopen();
public abstract void onmessage(String data);

View File

@@ -108,6 +108,10 @@ public abstract class Transport extends Emitter {
this.onPacket(Parser.decodePacket(data));
}
protected void onData(byte[] data) {
this.onPacket(Parser.decodePacket(data));
}
protected void onPacket(Packet packet) {
this.emit(EVENT_PACKET, packet);
}

View File

@@ -1,11 +1,11 @@
package com.github.nkzawa.engineio.client.transports;
import com.github.nkzawa.thread.EventThread;
import com.github.nkzawa.engineio.client.Transport;
import com.github.nkzawa.engineio.client.Util;
import com.github.nkzawa.engineio.parser.Packet;
import com.github.nkzawa.engineio.parser.Parser;
import com.github.nkzawa.thread.EventThread;
import java.util.Date;
import java.util.HashMap;
@@ -94,11 +94,20 @@ abstract public class Polling extends Transport {
this.emit(EVENT_POLL);
}
@Override
protected void onData(String data) {
_onData(data);
}
@Override
protected void onData(byte[] data) {
_onData(data);
}
private void _onData(Object data) {
final Polling self = this;
logger.fine(String.format("polling got data %s", data));
Parser.decodePayload(data, new Parser.DecodePayloadCallback() {
Parser.DecodePayloadCallback callback = new Parser.DecodePayloadCallback() {
@Override
public boolean call(Packet packet, int index, int total) {
if (self.readyState == ReadyState.OPENING) {
@@ -113,7 +122,13 @@ abstract public class Polling extends Transport {
self.onPacket(packet);
return true;
}
});
};
if (data instanceof String) {
Parser.decodePayload((String)data, callback);
} else if (data instanceof byte[]) {
Parser.decodePayload((byte[])data, callback);
}
if (this.readyState != ReadyState.CLOSED) {
this.polling = false;
@@ -134,7 +149,7 @@ abstract public class Polling extends Transport {
@Override
public void call(Object... args) {
logger.fine("writing close packet");
self.write(new Packet[] {new Packet(Packet.CLOSE, null)});
self.write(new Packet[] {new Packet(Packet.CLOSE)});
}
};
@@ -152,12 +167,19 @@ abstract public class Polling extends Transport {
protected void write(Packet[] packets) {
final Polling self = this;
this.writable = false;
this.doWrite(Parser.encodePayload(packets), new Runnable() {
final Runnable callbackfn = new Runnable() {
@Override
public void run() {
self.writable = true;
self.emit(EVENT_DRAIN);
}
};
Parser.encodePayload(packets, new Parser.EncodeCallback<byte[]>() {
@Override
public void call(byte[] data) {
self.doWrite(data, callbackfn);
}
});
}
@@ -187,7 +209,7 @@ abstract public class Polling extends Transport {
return schema + "://" + this.hostname + port + this.path + _query;
}
abstract protected void doWrite(String data, Runnable fn);
abstract protected void doWrite(byte[] data, Runnable fn);
abstract protected void doPoll();
}

View File

@@ -7,6 +7,9 @@ import com.github.nkzawa.thread.EventThread;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
@@ -57,7 +60,8 @@ public class PollingXHR extends Polling {
return req;
}
protected void doWrite(String data, final Runnable fn) {
@Override
protected void doWrite(byte[] data, final Runnable fn) {
Request.Options opts = new Request.Options();
opts.method = "POST";
opts.data = data;
@@ -90,6 +94,7 @@ public class PollingXHR extends Polling {
this.sendXhr = req;
}
@Override
protected void doPoll() {
logger.fine("xhr poll");
Request req = this.request();
@@ -100,8 +105,12 @@ public class PollingXHR extends Polling {
EventThread.exec(new Runnable() {
@Override
public void run() {
String data = args.length > 0 ? (String) args[0] : null;
self.onData(data);
Object arg = args.length > 0 ? args[0] : null;
if (arg instanceof String) {
self.onData((String)arg);
} else if (arg instanceof byte[]) {
self.onData((byte[])arg);
}
}
});
}
@@ -134,7 +143,7 @@ public class PollingXHR extends Polling {
String method;
String uri;
String data;
byte[] data;
HttpURLConnection xhr;
public Request(Options opts) {
@@ -159,7 +168,7 @@ public class PollingXHR extends Polling {
if ("POST".equals(this.method)) {
xhr.setDoOutput(true);
headers.put("Content-type", "text/plain;charset=UTF-8");
headers.put("Content-type", "application/octet-stream");
}
self.onRequestHeaders(headers);
@@ -171,15 +180,15 @@ public class PollingXHR extends Polling {
xhrService.submit(new Runnable() {
@Override
public void run() {
BufferedWriter writer = null;
OutputStream output = null;
InputStream input = null;
BufferedReader reader = null;
try {
if (self.data != null) {
byte[] data = self.data.getBytes("UTF-8");
xhr.setFixedLengthStreamingMode(data.length);
writer = new BufferedWriter(new OutputStreamWriter(xhr.getOutputStream()));
writer.write(self.data);
writer.flush();
xhr.setFixedLengthStreamingMode(self.data.length);
output = new BufferedOutputStream(xhr.getOutputStream());
output.write(self.data);
output.flush();
}
Map<String, String> headers = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
@@ -189,28 +198,46 @@ public class PollingXHR extends Polling {
}
self.onResponseHeaders(headers);
StringBuilder data = null;
final int statusCode = xhr.getResponseCode();
if (HttpURLConnection.HTTP_OK == statusCode) {
String contentType = xhr.getContentType();
if ("application/octet-stream".equalsIgnoreCase(contentType)) {
input = new BufferedInputStream(xhr.getInputStream());
List<byte[]> buffers = new ArrayList<byte[]>();
int capacity = 0;
int len = 0;
byte[] buffer = new byte[1024];
while ((len = input.read(buffer)) > 0) {
byte[] _buffer = new byte[len];
System.arraycopy(buffer, 0, _buffer, 0, len);
buffers.add(_buffer);
capacity += len;
}
ByteBuffer data = ByteBuffer.allocate(capacity);
for (byte[] b : buffers) {
data.put(b);
}
self.onData(data.array());
} else {
String line;
data = new StringBuilder();
StringBuilder data = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(xhr.getInputStream()));
while ((line = reader.readLine()) != null) {
data.append(line);
}
self.onData(data.toString());
}
} else {
self.onError(new IOException(Integer.toString(statusCode)));
}
if (data != null) {
self.onData(data.toString());
}
} catch (IOException e) {
self.onError(e);
} finally {
try {
if (writer != null) writer.close();
if (output != null) output.close();
} catch (IOException e) {}
try {
if (input != null) input.close();
} catch (IOException e) {}
try {
if (reader != null) reader.close();
@@ -230,6 +257,11 @@ public class PollingXHR extends Polling {
this.onSuccess();
}
private void onData(byte[] data) {
this.emit(EVENT_DATA, data);
this.onSuccess();
}
private void onError(Exception err) {
this.emit(EVENT_ERROR, err);
this.cleanup();
@@ -260,7 +292,7 @@ public class PollingXHR extends Polling {
public String uri;
public String method;
public String data;
public byte[] data;
}
}
}

View File

@@ -12,6 +12,7 @@ import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@@ -78,6 +79,15 @@ public class WebSocket extends Transport {
});
}
@Override
public void onMessage(final ByteBuffer s) {
EventThread.exec(new Runnable() {
@Override
public void run() {
self.onData(s.array());
}
});
}
@Override
public void onError(final Exception e) {
EventThread.exec(new Runnable() {
@Override
@@ -97,7 +107,16 @@ public class WebSocket extends Transport {
final WebSocket self = this;
this.writable = false;
for (Packet packet : packets) {
this.ws.send(Parser.encodePacket(packet));
Parser.encodePacket(packet, new Parser.EncodeCallback() {
@Override
public void call(Object packet) {
if (packet instanceof String) {
self.ws.send((String) packet);
} else if (packet instanceof byte[]) {
self.ws.send((byte[]) packet);
}
}
});
}
final Runnable ondrain = new Runnable() {

View File

@@ -1,7 +1,7 @@
package com.github.nkzawa.engineio.parser;
public class Packet {
public class Packet<T> {
static final public String OPEN = "open";
static final public String CLOSE = "close";
@@ -13,13 +13,14 @@ public class Packet {
static final public String ERROR = "error";
public String type;
public String data;
public T data;
public Packet(String type) {
this(type, null);
}
public Packet(String type, String data) {
public Packet(String type, T data) {
this.type = type;
this.data = data;
}

View File

@@ -1,12 +1,17 @@
package com.github.nkzawa.engineio.parser;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Parser {
public static final int protocol = 2;
public static final int protocol = 3;
private static final Map<String, Integer> packets = new HashMap<String, Integer>() {{
put(Packet.OPEN, 0);
put(Packet.CLOSE, 1);
@@ -16,54 +21,116 @@ public class Parser {
put(Packet.UPGRADE, 5);
put(Packet.NOOP, 6);
}};
private static final Map<Integer, String> bipackets = new HashMap<Integer, String>();
private static final Map<Integer, String> packetslist = new HashMap<Integer, String>();
static {
for (Map.Entry<String, Integer> entry : packets.entrySet()) {
bipackets.put(entry.getValue(), entry.getKey());
packetslist.put(entry.getValue(), entry.getKey());
}
}
private static Packet err = new Packet(Packet.ERROR, "parser error");
private static Packet<String> err = new Packet<String>(Packet.ERROR, "parser error");
private Parser() {}
public static String encodePacket(Packet packet) {
public static void encodePacket(Packet packet, EncodeCallback callback) {
if (packet.data instanceof byte[]) {
@SuppressWarnings("unchecked")
Packet<byte[]> _packet = packet;
@SuppressWarnings("unchecked")
EncodeCallback<byte[]> _callback = callback;
encodeByteArray(_packet, _callback);
return;
}
String encoded = String.valueOf(packets.get(packet.type));
if (packet.data != null) {
if (null != packet.data) {
encoded += packet.data;
}
return encoded;
@SuppressWarnings("unchecked")
EncodeCallback<String> _callback = callback;
_callback.call(encoded);
}
public static Packet decodePacket(String data) {
int type = -1;
private static void encodeByteArray(Packet<byte[]> packet, EncodeCallback<byte[]> callback) {
byte[] data = packet.data;
byte[] resultArray = new byte[1 + data.length];
resultArray[0] = packets.get(packet.type).byteValue();
System.arraycopy(data, 0, resultArray, 1, data.length);
callback.call(resultArray);
}
public static Packet<String> decodePacket(String data) {
int type;
try {
type = Character.getNumericValue(data.charAt(0));
} catch(IndexOutOfBoundsException e) {}
if (type < 0 || type >= packets.size()) {
} catch (IndexOutOfBoundsException e) {
type = -1;
}
if (type < 0 || type >= packetslist.size()) {
return err;
}
return new Packet(bipackets.get(type), data.length() > 1 ? data.substring(1) : null);
if (data.length() > 1) {
return new Packet<String>(packetslist.get(type), data.substring(1));
} else {
return new Packet<String>(packetslist.get(type));
}
}
public static String encodePayload(Packet[] packets) {
public static Packet<byte[]> decodePacket(byte[] data) {
int type = data[0];
byte[] intArray = new byte[data.length - 1];
System.arraycopy(data, 1, intArray, 0, intArray.length);
return new Packet<byte[]>(packetslist.get(type), intArray);
}
public static void encodePayload(Packet[] packets, EncodeCallback<byte[]> callback) {
if (packets.length == 0) {
return "0:";
callback.call(new byte[0]);
return;
}
StringBuilder encoded = new StringBuilder();
final ArrayList<ByteBuffer> results = new ArrayList<ByteBuffer>(packets.length);
for (Packet packet : packets) {
String message = encodePacket(packet);
encoded.append(message.length()).append(":").append(message);
encodePacket(packet, new EncodeCallback() {
@Override
public void call(Object packet) {
if (packet instanceof String) {
String encodingLength = String.valueOf(((String)packet).getBytes(Charset.forName("UTF-8")).length);
ByteBuffer sizeBuffer = ByteBuffer.allocate(encodingLength.length() + 2);
sizeBuffer.put((byte)0); // is a string
for (char ch : encodingLength.toCharArray()) {
sizeBuffer.put((byte)Character.getNumericValue(ch));
}
sizeBuffer.put((byte)255);
results.add(Buffer.concat(new ByteBuffer[] {sizeBuffer,
ByteBuffer.wrap(((String)packet).getBytes(Charset.forName("UTF-8")))}));
return;
}
return encoded.toString();
String encodingLength = String.valueOf(((ByteBuffer)packet).capacity());
ByteBuffer sizeBuffer = ByteBuffer.allocate(encodingLength.length() + 2);
sizeBuffer.put((byte)1); // is binary
for (char ch : encodingLength.toCharArray()) {
sizeBuffer.put((byte)ch);
}
sizeBuffer.put((byte)255);
results.add(Buffer.concat(new ByteBuffer[] {sizeBuffer, (ByteBuffer)packet}));
}
});
}
public static void decodePayload(String data, DecodePayloadCallback callback) {
callback.call(Buffer.concat(results.toArray(new ByteBuffer[results.size()])).array());
}
public static void decodePayload(String data, DecodePayloadCallback<String> callback) {
if (data == null || data.isEmpty()) {
callback.call(err, 0, 1);
return;
@@ -93,7 +160,8 @@ public class Parser {
}
if (msg.length() != 0) {
Packet packet = decodePacket(msg);
Packet<String> packet = decodePacket(msg);
if (err.type.equals(packet.type) && err.data.equals(packet.data)) {
callback.call(err, 0, 1);
return;
@@ -113,8 +181,91 @@ public class Parser {
}
}
public static interface DecodePayloadCallback {
public static void decodePayload(byte[] data, DecodePayloadCallback callback) {
ByteBuffer bufferTail = ByteBuffer.wrap(data);
List<Object> buffers = new ArrayList<Object>();
public boolean call(Packet packet, int index, int total);
while (bufferTail.capacity() > 0) {
StringBuilder strLen = new StringBuilder();
boolean isString = (bufferTail.get(0) & 0xFF) == 0;
for (int i = 1; ; i++) {
int b = bufferTail.get(i) & 0xFF;
if (b == 255) break;
strLen.append(b);
}
bufferTail.position(strLen.length() + 1);
bufferTail = bufferTail.slice();
int msgLength = Integer.parseInt(strLen.toString());
bufferTail.position(1);
bufferTail.limit(msgLength + 1);
byte[] msg = new byte[bufferTail.remaining()];
bufferTail.get(msg);
if (isString) {
buffers.add(new String(msg, Charset.forName("UTF-8")));
} else {
buffers.add(msg);
}
bufferTail.clear();
bufferTail.position(msgLength + 1);
bufferTail = bufferTail.slice();
}
int total = buffers.size();
for (int i = 0; i < total; i++) {
Object buffer = buffers.get(i);
if (buffer instanceof String) {
@SuppressWarnings("unchecked")
DecodePayloadCallback<String> _callback = callback;
_callback.call(decodePacket((String)buffer), i, total);
} else if (buffer instanceof byte[]) {
@SuppressWarnings("unchecked")
DecodePayloadCallback<byte[]> _callback = callback;
_callback.call(decodePacket((byte[])buffer), i, total);
}
}
}
public static interface EncodeCallback<T> {
public void call(T data);
}
public static interface DecodePayloadCallback<T> {
public boolean call(Packet<T> packet, int index, int total);
}
}
class Buffer {
private Buffer() {}
public static ByteBuffer concat(ByteBuffer[] list) {
int length = 0;
for (ByteBuffer buf : list) {
length += buf.capacity();
}
return concat(list, length);
}
public static ByteBuffer concat(ByteBuffer[] list, int length) {
if (list.length == 0) {
return ByteBuffer.allocate(0);
} else if (list.length == 1) {
return list[0];
}
ByteBuffer buffer = ByteBuffer.allocate(length);
for (ByteBuffer buf : list) {
buf.clear();
buffer.put(buf);
}
return buffer;
}
}

View File

@@ -15,91 +15,152 @@ public class ParserTest {
@Test
public void encodeAsString() {
assertThat(encodePacket(new Packet(Packet.MESSAGE, "test")), isA(String.class));
encodePacket(new Packet<String>(Packet.MESSAGE, "test"), new EncodeCallback<String>() {
@Override
public void call(String data) {
assertThat(data, isA(String.class));
}
});
}
@Test
public void decodeAsPacket() {
assertThat(decodePacket(encodePacket(new Packet(Packet.MESSAGE, "test"))), isA(Packet.class));
encodePacket(new Packet<String>(Packet.MESSAGE, "test"), new EncodeCallback<String>() {
@Override
public void call(String data) {
assertThat(decodePacket(data), isA(Packet.class));
}
});
}
@Test
public void noData() {
Packet p = decodePacket(encodePacket(new Packet(Packet.MESSAGE)));
encodePacket(new Packet(Packet.MESSAGE), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet p = decodePacket(data);
assertThat(p.type, is(Packet.MESSAGE));
assertThat(p.data, is(nullValue()));
}
});
}
@Test
public void encodeOpenPacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.OPEN, "{\"some\":\"json\"}")));
encodePacket(new Packet<String>(Packet.OPEN, "{\"some\":\"json\"}"), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet<String> p = decodePacket(data);
assertThat(p.type, is(Packet.OPEN));
assertThat(p.data, is("{\"some\":\"json\"}"));
}
});
}
@Test
public void encodeClosePacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.CLOSE)));
encodePacket(new Packet<String>(Packet.CLOSE), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet p = decodePacket(data);
assertThat(p.type, is(Packet.CLOSE));
}
});
}
@Test
public void encodePingPacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.PING, "1")));
encodePacket(new Packet<String>(Packet.PING, "1"), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet<String> p = decodePacket(data);
assertThat(p.type, is(Packet.PING));
assertThat(p.data, is("1"));
}
});
}
@Test
public void encodePongPacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.PONG, "1")));
encodePacket(new Packet<String>(Packet.PONG, "1"), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet<String> p = decodePacket(data);
assertThat(p.type, is(Packet.PONG));
assertThat(p.data, is("1"));
}
});
}
@Test
public void encodeMessagePacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.MESSAGE, "aaa")));
encodePacket(new Packet<String>(Packet.MESSAGE, "aaa"), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet<String> p = decodePacket(data);
assertThat(p.type, is(Packet.MESSAGE));
assertThat(p.data, is("aaa"));
}
});
}
@Test
public void encodeUpgradePacket() {
Packet p = decodePacket(encodePacket(new Packet(Packet.UPGRADE)));
encodePacket(new Packet<String>(Packet.UPGRADE), new EncodeCallback<String>() {
@Override
public void call(String data) {
Packet p = decodePacket(data);
assertThat(p.type, is(Packet.UPGRADE));
}
});
}
@Test
public void encodingFormat() {
assertThat(encodePacket(new Packet(Packet.MESSAGE, "test")).matches("[0-9].*"), is(true));
assertThat(encodePacket(new Packet(Packet.MESSAGE)).matches("[0-9]"), is(true));
encodePacket(new Packet<String>(Packet.MESSAGE, "test"), new EncodeCallback<String>() {
@Override
public void call(String data) {
assertThat(data.matches("[0-9].*"), is(true));
}
});
encodePacket(new Packet<String>(Packet.MESSAGE), new EncodeCallback<String>() {
@Override
public void call(String data) {
assertThat(data.matches("[0-9]"), is(true));
}
});
}
@Test
public void decodeBadFormat() {
Packet p = decodePacket(":::");
Packet<String> p = decodePacket(":::");
assertThat(p.type, is(Packet.ERROR));
assertThat(p.data, is(ERROR_DATA));
}
@Test
public void decodeInexistentTypes() {
Packet p = decodePacket("94103");
Packet<String> p = decodePacket("94103");
assertThat(p.type, is(Packet.ERROR));
assertThat(p.data, is(ERROR_DATA));
}
@Test
public void encodePayloadsAsString() {
assertThat(encodePayload(new Packet[] {
new Packet(Packet.PING), new Packet(Packet.PONG)}), isA(String.class));
public void encodePayloads() {
encodePayload(new Packet[]{new Packet(Packet.PING), new Packet(Packet.PONG)}, new EncodeCallback<byte[]>() {
@Override
public void call(byte[] data) {
assertThat(data, isA(byte[].class));
}
});
}
@Test
public void encodeAndDecodePayloads() {
decodePayload(encodePayload(new Packet[] {new Packet(Packet.MESSAGE, "a")}),
new DecodePayloadCallback() {
encodePayload(new Packet[] {new Packet<String>(Packet.MESSAGE, "a")}, new EncodeCallback<byte[]>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
@Override
public boolean call(Packet packet, int index, int total) {
boolean isLast = index + 1 == total;
@@ -107,9 +168,12 @@ public class ParserTest {
return true;
}
});
decodePayload(encodePayload(new Packet[] {
new Packet(Packet.MESSAGE, "a"), new Packet(Packet.PING)}),
new DecodePayloadCallback() {
}
});
encodePayload(new Packet[]{new Packet<String>(Packet.MESSAGE, "a"), new Packet(Packet.PING)}, new EncodeCallback<byte[]>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
@Override
public boolean call(Packet packet, int index, int total) {
boolean isLast = index + 1 == total;
@@ -122,10 +186,15 @@ public class ParserTest {
}
});
}
});
}
@Test
public void encodeAndDecodeEmptyPayloads() {
decodePayload(encodePayload(new Packet[] {}), new DecodePayloadCallback() {
encodePayload(new Packet[] {}, new EncodeCallback<byte[]>() {
@Override
public void call(byte[] data) {
decodePayload(data, new DecodePayloadCallback() {
@Override
public boolean call(Packet packet, int index, int total) {
assertThat(packet.type, is(Packet.OPEN));
@@ -135,12 +204,14 @@ public class ParserTest {
}
});
}
});
}
@Test
public void decodePayloadBadFormat() {
decodePayload("1!", new DecodePayloadCallback() {
decodePayload("1!", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -148,9 +219,9 @@ public class ParserTest {
return true;
}
});
decodePayload("", new DecodePayloadCallback() {
decodePayload("", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -158,9 +229,9 @@ public class ParserTest {
return true;
}
});
decodePayload("))", new DecodePayloadCallback() {
decodePayload("))", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -172,9 +243,9 @@ public class ParserTest {
@Test
public void decodePayloadBadLength() {
decodePayload("1:", new DecodePayloadCallback() {
decodePayload("1:", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -186,9 +257,9 @@ public class ParserTest {
@Test
public void decodePayloadBadPacketFormat() {
decodePayload("3:99:", new DecodePayloadCallback() {
decodePayload("3:99:", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -196,9 +267,9 @@ public class ParserTest {
return true;
}
});
decodePayload("1:aa", new DecodePayloadCallback() {
decodePayload("1:aa", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));
@@ -206,9 +277,9 @@ public class ParserTest {
return true;
}
});
decodePayload("1:a2:b", new DecodePayloadCallback() {
decodePayload("1:a2:b", new DecodePayloadCallback<String>() {
@Override
public boolean call(Packet packet, int index, int total) {
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));

View File

@@ -3,6 +3,6 @@
"version": "0.0.0",
"private": true,
"dependencies": {
"engine.io": "0.8.2"
"engine.io": "1.0.5"
}
}