aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOle André Vadla Ravnås <ole.andre.ravnas@soundrop.com>2013-07-23 17:44:31 +0200
committerOle André Vadla Ravnås <ole.andre.ravnas@soundrop.com>2013-09-26 15:27:42 +0200
commit1b7f44cd463aa1dcfe6bd5a682c15ca21e0352b5 (patch)
tree5796df2c2983f5b9c8dc9a4c82081576fa5b1cdc
parent6700db32923d6f8da14a40562d03a57821d67084 (diff)
downloadAndroidAsync-1b7f44cd463aa1dcfe6bd5a682c15ca21e0352b5.tar.gz
AndroidAsync-1b7f44cd463aa1dcfe6bd5a682c15ca21e0352b5.tar.bz2
AndroidAsync-1b7f44cd463aa1dcfe6bd5a682c15ca21e0352b5.zip
Add support for the x-webkit-deflate-frame extension
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java42
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java16
2 files changed, 52 insertions, 6 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java b/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
index 9d23425..05b70d4 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
@@ -40,16 +40,20 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
abstract class HybiParser {
private static final String TAG = "HybiParser";
private boolean mMasking = true;
+ private boolean mDeflate = false;
private int mStage;
private boolean mFinal;
private boolean mMasked;
+ private boolean mDeflated;
private int mOpcode;
private int mLengthSize;
private int mLength;
@@ -61,6 +65,8 @@ abstract class HybiParser {
private boolean mClosed = false;
private ByteArrayOutputStream mBuffer = new ByteArrayOutputStream();
+ private Inflater mInflater = new Inflater(true);
+ private byte[] mInflateBuffer = new byte[4096];
private static final int BYTE = 255;
private static final int FIN = 128;
@@ -106,11 +112,33 @@ abstract class HybiParser {
}
return payload;
}
-
+
+ private byte[] inflate(byte[] payload) throws DataFormatException {
+ ByteArrayOutputStream inflated = new ByteArrayOutputStream();
+
+ mInflater.setInput(payload);
+ while (!mInflater.needsInput()) {
+ int chunkSize = mInflater.inflate(mInflateBuffer);
+ inflated.write(mInflateBuffer, 0, chunkSize);
+ }
+
+ mInflater.setInput(new byte[] { 0, 0, -1, -1 });
+ while (!mInflater.needsInput()) {
+ int chunkSize = mInflater.inflate(mInflateBuffer);
+ inflated.write(mInflateBuffer, 0, chunkSize);
+ }
+
+ return inflated.toByteArray();
+ }
+
public void setMasking(boolean masking) {
mMasking = masking;
}
-
+
+ public void setDeflate(boolean deflate) {
+ mDeflate = deflate;
+ }
+
DataCallback mStage0 = new DataCallback() {
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
@@ -208,12 +236,13 @@ abstract class HybiParser {
boolean rsv2 = (data & RSV2) == RSV2;
boolean rsv3 = (data & RSV3) == RSV3;
- if (rsv1 || rsv2 || rsv3) {
+ if ((!mDeflate && rsv1) || rsv2 || rsv3) {
throw new ProtocolError("RSV not zero");
}
mFinal = (data & FIN) == FIN;
mOpcode = (data & OPCODE);
+ mDeflated = rsv1;
mMask = new byte[0];
mPayload = new byte[0];
@@ -324,6 +353,13 @@ abstract class HybiParser {
private void emitFrame() throws IOException {
byte[] payload = mask(mPayload, mMask, 0);
+ if (mDeflated) {
+ try {
+ payload = inflate(payload);
+ } catch (DataFormatException e) {
+ throw new IOException("Invalid deflated data");
+ }
+ }
int opcode = mOpcode;
if (opcode == OP_CONTINUATION) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
index c96fcad..71e5663 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
@@ -71,7 +71,7 @@ public class WebSocketImpl implements WebSocket {
pending = null;
}
- private void setupParser(boolean masking) {
+ private void setupParser(boolean masking, boolean deflate) {
mParser = new HybiParser(mSocket) {
@Override
protected void report(Exception ex) {
@@ -100,6 +100,7 @@ public class WebSocketImpl implements WebSocket {
}
};
mParser.setMasking(masking);
+ mParser.setDeflate(deflate);
if (mSocket.isPaused())
mSocket.resume();
}
@@ -126,7 +127,7 @@ public class WebSocketImpl implements WebSocket {
// response.getHeaders().getHeaders().set("Access-Control-Allow-Origin", "http://" + origin);
response.writeHead();
- setupParser(false);
+ setupParser(false, false);
}
public static void addWebSocketUpgradeHeaders(AsyncHttpRequest req, String protocol) {
@@ -134,6 +135,7 @@ public class WebSocketImpl implements WebSocket {
final String key = Base64.encodeToString(toByteArray(UUID.randomUUID()),Base64.NO_WRAP);
headers.set("Sec-WebSocket-Version", "13");
headers.set("Sec-WebSocket-Key", key);
+ headers.set("Sec-WebSocket-Extensions", "x-webkit-deflate-frame");
headers.set("Connection", "Upgrade");
headers.set("Upgrade", "websocket");
if (protocol != null)
@@ -166,9 +168,17 @@ public class WebSocketImpl implements WebSocket {
String expected = SHA1(concat).trim();
if (!sha1.equalsIgnoreCase(expected))
return null;
+ String extensions = requestHeaders.get("Sec-WebSocket-Extensions");
+ boolean deflate = false;
+ if (extensions != null) {
+ if (extensions.equals("x-webkit-deflate-frame"))
+ deflate = true;
+ else
+ return null;
+ }
WebSocketImpl ret = new WebSocketImpl(response.detachSocket());
- ret.setupParser(true);
+ ret.setupParser(true, deflate);
return ret;
}