aboutsummaryrefslogtreecommitdiffstats
path: root/AndroidAsync
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2014-07-23 23:52:42 -0700
committerKoushik Dutta <koushd@gmail.com>2014-07-23 23:52:42 -0700
commitad5709a17b41306f76fc446673bb5779fcd98666 (patch)
tree6362f0dd8d59df852954792acecf76250521a544 /AndroidAsync
parent26c3c5bf969faadaf3d001b58c4c2731b9b0154a (diff)
downloadAndroidAsync-ad5709a17b41306f76fc446673bb5779fcd98666.tar.gz
AndroidAsync-ad5709a17b41306f76fc446673bb5779fcd98666.tar.bz2
AndroidAsync-ad5709a17b41306f76fc446673bb5779fcd98666.zip
Fix header chunking bug in AsyncHttpServerResponseImpl.
Fix resume bugs in ChunkedInputFilter.
Diffstat (limited to 'AndroidAsync')
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java11
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java9
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java52
3 files changed, 35 insertions, 37 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
index 5413896..0f777e6 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
@@ -140,17 +140,6 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
}
});
-
- // here's the stack of emitters
- // ssl emitter
- // buffered data emitter
- // socket
-
- // ssl emitter needs a buffered emitter
- // in case there is an underflow.
- // buffered emitter will read from the socket,
- // and replay data forever.
-
// on pause, the emitter is paused to prevent the buffered
// socket and itself from firing.
// on resume, emitter is resumed, ssl buffer is flushed as well
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java b/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
index 652e907..f049a06 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
@@ -43,6 +43,7 @@ public class ChunkedInputFilter extends FilteredDataEmitter {
super.report(e);
}
+ ByteBufferList pending = new ByteBufferList();
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
try {
@@ -82,12 +83,8 @@ public class ChunkedInputFilter extends FilteredDataEmitter {
}
if (reading == 0)
break;
- ByteBufferList chunk = bb.get(reading);
- int newRemaining = bb.remaining();
- assert remaining == chunk.remaining() + bb.remaining();
- assert reading == chunk.remaining();
- Util.emitAllData(this, chunk);
- assert newRemaining == bb.remaining();
+ bb.get(pending, reading);
+ Util.emitAllData(this, pending);
break;
case CHUNK_CR:
if (!checkCR(bb.getByteChar()))
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
index fbf4ba2..cdbfa5c 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
@@ -51,18 +51,21 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
@Override
public void write(ByteBufferList bb) {
- if (bb.remaining() == 0)
- return;
-
+ // order is important here...
assert !mEnded;
- if (!mHasWritten) {
+ // do the header write... this will call onWritable, which may be reentrant
+ if (!mHasWritten)
initFirstWrite();
+
+ // now check to see if the list is empty. reentrancy may cause it to empty itself.
+ if (bb.remaining() == 0)
return;
- }
- if (mSink == null) {
- System.out.println("poop squat");
+
+ // null sink means that the header has not finished writing
+ if (mSink == null)
return;
- }
+
+ // can successfully write!
mSink.write(bb);
}
@@ -74,23 +77,32 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
mHasWritten = true;
+ final boolean isChunked;
+ String currentEncoding = mRawHeaders.get("Transfer-Encoding");
+ if ("".equals(currentEncoding))
+ mRawHeaders.removeAll("Transfer-Encoding");
+ boolean canUseChunked = ("Chunked".equalsIgnoreCase(currentEncoding) || currentEncoding == null)
+ && !"close".equalsIgnoreCase(mRawHeaders.get("Connection"));
+ if (mContentLength < 0) {
+ String contentLength = mRawHeaders.get("Content-Length");
+ if (!TextUtils.isEmpty(contentLength))
+ mContentLength = Long.valueOf(contentLength);
+ }
+ if (mContentLength < 0 && canUseChunked) {
+ mRawHeaders.set("Transfer-Encoding", "Chunked");
+ isChunked = true;
+ }
+ else {
+ isChunked = false;
+ }
+
String statusLine = String.format("HTTP/1.1 %s %s", code, AsyncHttpServer.getResponseCodeDescription(code));
String rh = mRawHeaders.toPrefixString(statusLine);
+
Util.writeAll(mSocket, rh.getBytes(), new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
- String currentEncoding = mRawHeaders.get("Transfer-Encoding");
- if ("".equals(currentEncoding))
- mRawHeaders.removeAll("Transfer-Encoding");
- boolean canUseChunked = ("Chunked".equalsIgnoreCase(currentEncoding) || currentEncoding == null)
- && !"close".equalsIgnoreCase(mRawHeaders.get("Connection"));
- if (mContentLength < 0) {
- String contentLength = mRawHeaders.get("Content-Length");
- if (!TextUtils.isEmpty(contentLength))
- mContentLength = Long.valueOf(contentLength);
- }
- if (mContentLength < 0 && canUseChunked) {
- mRawHeaders.set("Transfer-Encoding", "Chunked");
+ if (isChunked) {
ChunkedOutputFilter chunked = new ChunkedOutputFilter(mSocket);
chunked.setMaxBuffer(0);
mSink = chunked;