Skip to content

Commit 1589f55

Browse files
committed
add support for range requests
Change-Id: I56b546d55167c61f315b3cfa3ad9eee54d85defd
1 parent 82d3e8b commit 1589f55

File tree

5 files changed

+57
-9
lines changed

5 files changed

+57
-9
lines changed

AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public void run() {
8181
handleRemaining(list.remaining());
8282
}
8383
catch (IOException e) {
84-
close();
84+
closeInternal();
8585
reportEndPending(e);
8686
reportClose(e);
8787
}
@@ -122,7 +122,7 @@ public void run() {
122122
handleRemaining(b.remaining());
123123
}
124124
catch (IOException ex) {
125-
close();
125+
closeInternal();
126126
reportEndPending(ex);
127127
reportClose(ex);
128128
}

AndroidAsync/src/com/koushikdutta/async/DataEmitterReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public void read(int count, DataCallback callback) {
1111
assert mPendingRead == null;
1212
mPendingReadLength = count;
1313
mPendingRead = callback;
14-
mPendingData = new ByteBufferList();
14+
mPendingData.recycle();
1515
}
1616

1717
private boolean handlePendingData(DataEmitter emitter) {

AndroidAsync/src/com/koushikdutta/async/Util.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public static void emitAllData(DataEmitter emitter, ByteBufferList list) {
4040
}
4141

4242
public static void pump(final InputStream is, final DataSink ds, final CompletedCallback callback) {
43+
pump(is, Integer.MAX_VALUE, ds, callback);
44+
}
45+
46+
public static void pump(final InputStream is, final int max, final DataSink ds, final CompletedCallback callback) {
4347
final CompletedCallback wrapper = new CompletedCallback() {
4448
boolean reported;
4549
@Override
@@ -52,6 +56,7 @@ public void onCompleted(Exception ex) {
5256
};
5357

5458
final WritableCallback cb = new WritableCallback() {
59+
int totalRead = 0;
5560
private void close() {
5661
try {
5762
is.close();
@@ -70,15 +75,16 @@ private void close() {
7075
public void onWriteable() {
7176
try {
7277
int remaining;
73-
// long start = System.currentTimeMillis();
7478
do {
7579
if (pending.remaining() == 0) {
76-
int read = is.read(buffer);
77-
if (read == -1) {
80+
int toRead = Math.min(max - totalRead, buffer.length);
81+
int read = is.read(buffer, 0, toRead);
82+
if (read == -1 || totalRead == max) {
7883
close();
7984
wrapper.onCompleted(null);
8085
return;
8186
}
87+
totalRead += read;
8288
pending.position(0);
8389
pending.limit(read);
8490
}

AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ public void onCompleted(Exception ex) {
393393
private static Hashtable<Integer, String> mCodes = new Hashtable<Integer, String>();
394394
static {
395395
mCodes.put(200, "OK");
396+
mCodes.put(206, "Partial Content");
396397
mCodes.put(101, "Switching Protocols");
397398
mCodes.put(404, "Not Found");
398399
}

AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.koushikdutta.async.http.server;
22

3+
import android.text.TextUtils;
4+
35
import com.koushikdutta.async.*;
46
import com.koushikdutta.async.callback.CompletedCallback;
57
import com.koushikdutta.async.callback.WritableCallback;
@@ -11,6 +13,7 @@
1113
import java.io.File;
1214
import java.io.FileInputStream;
1315
import java.io.FileNotFoundException;
16+
import java.io.IOException;
1417
import java.io.UnsupportedEncodingException;
1518
import java.nio.ByteBuffer;
1619

@@ -159,18 +162,56 @@ public void send(JSONObject json) {
159162
}
160163

161164
public void sendFile(File file) {
165+
int start = 0;
166+
int end = (int)file.length();
167+
168+
String range = mRequest.getHeaders().getHeaders().get("Range");
169+
if (range != null) {
170+
String[] parts = range.split("=");
171+
if (parts.length != 2 || !"bytes".equals(parts[0])) {
172+
// Requested range not satisfiable
173+
responseCode(416);
174+
end();
175+
return;
176+
}
177+
178+
parts = parts[1].split("-");
179+
try {
180+
if (parts.length > 2)
181+
throw new Exception();
182+
if (!TextUtils.isEmpty(parts[0]))
183+
start = Integer.parseInt(parts[0]);
184+
if (parts.length == 2 && !TextUtils.isEmpty(parts[1]))
185+
end = Integer.parseInt(parts[1]);
186+
else if (start != 0)
187+
end = (int)file.length();
188+
else
189+
end = Math.min((int)file.length(), start + 50000);
190+
191+
responseCode(206);
192+
getHeaders().getHeaders().set("Content-Range", String.format("bytes %d-%d/%d", start, end - 1, file.length()));
193+
}
194+
catch (Exception e) {
195+
responseCode(416);
196+
end();
197+
return;
198+
}
199+
}
162200
try {
163201
FileInputStream fin = new FileInputStream(file);
202+
if (start != fin.skip(start))
203+
throw new Exception();
164204
mRawHeaders.set("Content-Type", AsyncHttpServer.getContentType(file.getAbsolutePath()));
165-
responseCode(200);
166-
Util.pump(fin, this, new CompletedCallback() {
205+
if (getHeaders().getHeaders().getStatusLine() == null)
206+
responseCode(200);
207+
Util.pump(fin, end - start, this, new CompletedCallback() {
167208
@Override
168209
public void onCompleted(Exception ex) {
169210
end();
170211
}
171212
});
172213
}
173-
catch (FileNotFoundException e) {
214+
catch (Exception e) {
174215
responseCode(404);
175216
end();
176217
}

0 commit comments

Comments
 (0)