aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncServer.java6
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSocketImpl.java14
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java10
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/Continuation.java54
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java21
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/Util.java23
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java87
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/callback/ContinuationCallback.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java20
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/HeaderMap.java24
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java26
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/Part.java34
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java216
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java18
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java22
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java13
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/WebSocketImpl.java4
-rw-r--r--AndroidAsync/src/com/koushikdutta/test/TestActivity.java3
-rw-r--r--AndroidAsyncSample/gen/com/koushikdutta/async/R.java35
-rw-r--r--AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java18
23 files changed, 507 insertions, 165 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java b/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
index e077566..c88d14a 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
@@ -70,7 +70,7 @@ public class AsyncServer {
final ChannelWrapper sc = handler.getChannel();
SelectionKey ckey = sc.register(mSelector);
ckey.attach(handler);
- handler.mKey = ckey;
+ handler.setup(this, ckey);
}
public void post(Runnable runnable) {
@@ -366,7 +366,7 @@ public class AsyncServer {
ListenCallback serverHandler = (ListenCallback) key.attachment();
AsyncSocketImpl handler = new AsyncSocketImpl();
handler.attach(sc);
- handler.mKey = ckey;
+ handler.setup(server, ckey);
ckey.attach(handler);
serverHandler.onAccepted(handler);
}
@@ -386,7 +386,7 @@ public class AsyncServer {
try {
sc.finishConnect();
AsyncSocketImpl newHandler = new AsyncSocketImpl();
- newHandler.mKey = key;
+ newHandler.setup(server, key);
newHandler.attach(sc);
key.attach(newHandler);
handler.onConnectCompleted(null, newHandler);
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSocketImpl.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSocketImpl.java
index 639ca39..997f097 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncSocketImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSocketImpl.java
@@ -39,10 +39,19 @@ class AsyncSocketImpl implements AsyncSocket {
}
private ChannelWrapper mChannel;
- SelectionKey mKey;
+ private SelectionKey mKey;
+// private AsyncServer mServer;
+ private Thread mAffinity;
+
+ void setup(AsyncServer server, SelectionKey key) {
+ mAffinity = Thread.currentThread();
+// mServer = server;
+ mKey = key;
+ }
@Override
public void write(ByteBufferList list) {
+ Assert.assertEquals(mAffinity, Thread.currentThread());
if (!mChannel.isConnected()) {
Assert.assertFalse(mChannel.isChunked());
return;
@@ -73,6 +82,7 @@ class AsyncSocketImpl implements AsyncSocket {
@Override
public void write(ByteBuffer b) {
+ Assert.assertEquals(mAffinity, Thread.currentThread());
try {
if (!mChannel.isConnected()) {
Assert.assertFalse(mChannel.isChunked());
@@ -241,6 +251,7 @@ class AsyncSocketImpl implements AsyncSocket {
boolean mPaused = false;
@Override
public void pause() {
+ Assert.assertEquals(mAffinity, Thread.currentThread());
if (mPaused)
return;
mPaused = true;
@@ -264,6 +275,7 @@ class AsyncSocketImpl implements AsyncSocket {
@Override
public void resume() {
+ Assert.assertEquals(mAffinity, Thread.currentThread());
if (!mPaused)
return;
mPaused = false;
diff --git a/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java b/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
index b2b25fc..7071957 100644
--- a/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
+++ b/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
@@ -15,6 +15,16 @@ public class ByteBufferList implements Iterable<ByteBuffer> {
public ByteBufferList() {
}
+
+ public ByteBufferList(ByteBuffer b) {
+ add(b);
+ }
+
+ public ByteBufferList(byte[] buf) {
+ super();
+ ByteBuffer b = ByteBuffer.wrap(buf);
+ add(b);
+ }
public ByteBuffer[] toArray() {
ByteBuffer[] ret = new ByteBuffer[mBuffers.size()];
diff --git a/AndroidAsync/src/com/koushikdutta/async/Continuation.java b/AndroidAsync/src/com/koushikdutta/async/Continuation.java
new file mode 100644
index 0000000..e9b1719
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/Continuation.java
@@ -0,0 +1,54 @@
+package com.koushikdutta.async;
+
+import java.util.LinkedList;
+
+import junit.framework.Assert;
+
+import com.koushikdutta.async.callback.CompletedCallback;
+import com.koushikdutta.async.callback.ContinuationCallback;
+
+public class Continuation {
+ CompletedCallback callback;
+ CompletedCallback wrapper;
+ public Continuation(CompletedCallback callback) {
+ this.callback = callback;
+ wrapper = new CompletedCallback() {
+ @Override
+ public void onCompleted(Exception ex) {
+ if (ex == null) {
+ next();
+ return;
+ }
+ Continuation.this.callback.onCompleted(ex);
+ }
+ };
+ }
+
+ LinkedList<ContinuationCallback> mCallbacks = new LinkedList<ContinuationCallback>();
+
+ public void add(ContinuationCallback callback) {
+ mCallbacks.add(callback);
+ }
+
+ private void next() {
+ if (mCallbacks.size() > 0) {
+ ContinuationCallback cb = mCallbacks.remove();
+ try {
+ cb.onContinue(wrapper);
+ }
+ catch (Exception e) {
+ callback.onCompleted(e);
+ }
+ return;
+ }
+
+ callback.onCompleted(null);
+ }
+
+ boolean started;
+ public void start() {
+ Assert.assertTrue(!started);
+ started = true;
+ next();
+ }
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java b/AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java
index 64efffe..9b61fec 100644
--- a/AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java
+++ b/AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java
@@ -17,9 +17,25 @@ public class FilteredDataSink implements DataSink {
mPendingWritable = false;
mWritable.onWriteable();
}
+ testFlushed();
}
});
}
+
+ private void testFlushed() {
+ if (mPending == null)
+ onFlushed();
+ }
+
+ protected void onFlushed() {
+ }
+
+ public int getPending() {
+ if (mPending == null)
+ return 0;
+ return mPending.remaining();
+ }
+
DataSink mSink;
public DataSink getSink() {
return mSink;
@@ -63,19 +79,20 @@ public class FilteredDataSink implements DataSink {
return false;
return true;
}
-
+
@Override
public final void write(ByteBufferList bb) {
if (!handlePending(bb))
return;
ByteBufferList filtered = filter(bb);
- Assert.assertTrue(filtered == bb || bb.remaining() == 0);
+ Assert.assertTrue(bb == null || filtered == bb || bb.remaining() == 0);
mSink.write(filtered);
if (filtered.remaining() > 0) {
mPending = new ByteBufferList();
mPending.add(filtered.read(filtered.remaining()));
}
bb.clear();
+ testFlushed();
}
WritableCallback mWritable;
diff --git a/AndroidAsync/src/com/koushikdutta/async/Util.java b/AndroidAsync/src/com/koushikdutta/async/Util.java
index 4e14fc7..2710b4a 100644
--- a/AndroidAsync/src/com/koushikdutta/async/Util.java
+++ b/AndroidAsync/src/com/koushikdutta/async/Util.java
@@ -1,5 +1,7 @@
package com.koushikdutta.async;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
@@ -89,6 +91,27 @@ public class Util {
cb.onWriteable();
}
+ public static void pump(final File file, final DataSink ds, final CompletedCallback callback) {
+ try {
+ final InputStream is = new FileInputStream(file);
+ pump(is, ds, new CompletedCallback() {
+ @Override
+ public void onCompleted(Exception ex) {
+ try {
+ is.close();
+ callback.onCompleted(ex);
+ }
+ catch (IOException e) {
+ callback.onCompleted(e);
+ }
+ }
+ });
+ }
+ catch (Exception e) {
+ callback.onCompleted(e);
+ }
+ }
+
public static void writeAll(final DataSink sink, final ByteBufferList bb, final CompletedCallback callback) {
sink.setWriteableCallback(new WritableCallback() {
@Override
diff --git a/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java b/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java
new file mode 100644
index 0000000..3014ca3
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java
@@ -0,0 +1,87 @@
+package com.koushikdutta.async;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import com.koushikdutta.async.callback.CompletedCallback;
+
+public class ZipDataSink extends FilteredDataSink implements CompletedEmitter {
+ public ZipDataSink(DataSink sink) {
+ super(sink);
+ }
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ZipOutputStream zop = new ZipOutputStream(bout);
+ boolean first = true;
+
+ public void putNextEntry(ZipEntry ze) throws IOException {
+ zop.putNextEntry(ze);
+ }
+
+ public void closeEntry() throws IOException {
+ zop.closeEntry();
+ }
+
+ protected void report(Exception e) {
+ if (mCompleted != null)
+ mCompleted.onCompleted(null);
+ }
+
+ private boolean closed = false;
+ public void close() {
+ closed = true;
+ try {
+ zop.close();
+ }
+ catch (IOException e) {
+ report(e);
+ return;
+ }
+ write(new ByteBufferList());
+ }
+
+
+ @Override
+ protected void onFlushed() {
+ if (closed) {
+ if (bout.size() > 0) {
+ write(new ByteBufferList());
+ return;
+ }
+ report(null);
+ }
+ }
+
+ @Override
+ public ByteBufferList filter(ByteBufferList bb) {
+ try {
+ if (bb != null) {
+ for (ByteBuffer b: bb) {
+ zop.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
+ }
+ }
+ ByteBufferList ret = new ByteBufferList(bout.toByteArray());
+ bout.reset();
+ bb.clear();
+ return ret;
+ }
+ catch (IOException e) {
+ report(e);
+ return null;
+ }
+ }
+
+ private CompletedCallback mCompleted;
+ @Override
+ public void setCompletedCallback(CompletedCallback callback) {
+ mCompleted = callback;
+ }
+
+ @Override
+ public CompletedCallback getCompletedCallback() {
+ return mCompleted;
+ }
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/callback/ContinuationCallback.java b/AndroidAsync/src/com/koushikdutta/async/callback/ContinuationCallback.java
new file mode 100644
index 0000000..71508ac
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/callback/ContinuationCallback.java
@@ -0,0 +1,5 @@
+package com.koushikdutta.async.callback;
+
+public interface ContinuationCallback {
+ public void onContinue(CompletedCallback next) throws Exception;
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
index 0a36a72..517bf1b 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
@@ -302,6 +302,26 @@ public class AsyncHttpClient {
}
}
+ public static class WebSocketCallback implements CompletedCallback {
+ @Override
+ public void onCompleted(Exception ex) {
+ }
+ }
+
+ public static void websocket(String uri, final WebSocketCallback callback) {
+ try {
+ execute(new AsyncHttpGet(uri), new HttpConnectCallback() {
+ @Override
+ public void onConnectCompleted(Exception ex, AsyncHttpResponse response) {
+// response.get
+ }
+ });
+ }
+ catch (URISyntaxException e) {
+ callback.onCompleted(e);
+ }
+ }
+
public static void execute(AsyncHttpRequest req, final String filename, final FileCallback callback) {
final Handler handler = Looper.myLooper() == null ? null : new Handler();
final File file = new File(filename);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/HeaderMap.java b/AndroidAsync/src/com/koushikdutta/async/http/HeaderMap.java
new file mode 100644
index 0000000..81e0abb
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/http/HeaderMap.java
@@ -0,0 +1,24 @@
+package com.koushikdutta.async.http;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.koushikdutta.async.http.libcore.RawHeaders;
+
+public class HeaderMap {
+ public static Map<String,String> parse(RawHeaders headers, String header) {
+ HashMap<String, String> map = new HashMap<String, String>();
+ String value = headers.get(header);
+ String[] parts = value.split(";");
+ for (String part: parts) {
+ String[] pair = part.split("=", 2);
+ String key = pair[0].trim();
+ String v = null;
+ if (pair.length > 1)
+ v = pair[1];
+ map.put(key, v);
+ }
+ return Collections.unmodifiableMap(map);
+ }
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java b/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java
new file mode 100644
index 0000000..f3f3026
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java
@@ -0,0 +1,7 @@
+package com.koushikdutta.async.http;
+
+import com.koushikdutta.async.callback.DataCallback;
+
+public interface MultipartCallback {
+ public DataCallback onPart(Part part);
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java b/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
index 2f5cbcb..53035f6 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
@@ -33,15 +33,16 @@ public class MultipartFormDataBody extends AsyncHttpRequestBodyBase {
headers.addLine(s);
}
else {
- DataCallback callback = onPart(headers);
+ Part part = new Part(headers);
+ DataCallback callback = onPart(part);
if (callback == null)
callback = new DataCallback() {
int total;
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
total += bb.remaining();
- System.out.println(total);
- System.out.println(bb.peekString());
+// System.out.println(total);
+// System.out.println(bb.peekString());
bb.clear();
}
};
@@ -52,7 +53,7 @@ public class MultipartFormDataBody extends AsyncHttpRequestBodyBase {
}
@Override
protected void onBoundaryEnd() {
- System.out.println("boundary end");
+// System.out.println("boundary end");
}
};
return;
@@ -65,7 +66,20 @@ public class MultipartFormDataBody extends AsyncHttpRequestBodyBase {
boundaryEmitter.onDataAvailable(emitter, bb);
}
- public DataCallback onPart(RawHeaders headers) {
- return null;
+ MultipartCallback mCallback;
+ public void setMultipartCallback(MultipartCallback callback) {
+ mCallback = callback;
+ }
+
+ public MultipartCallback getMultipartCallback() {
+ return mCallback;
+ }
+
+ private DataCallback onPart(Part part) {
+// System.out.println("here");
+// System.out.println(headers.toHeaderString());
+ if (mCallback == null)
+ return null;
+ return mCallback.onPart(part);
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/Part.java b/AndroidAsync/src/com/koushikdutta/async/http/Part.java
new file mode 100644
index 0000000..61c9afc
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/http/Part.java
@@ -0,0 +1,34 @@
+package com.koushikdutta.async.http;
+
+import java.io.File;
+import java.util.Map;
+
+import com.koushikdutta.async.http.libcore.RawHeaders;
+
+public class Part {
+ RawHeaders mHeaders;
+ Map<String, String> mContentDisposition;
+ public Part(RawHeaders headers) {
+ mHeaders = headers;
+ mContentDisposition = HeaderMap.parse(mHeaders, "Content-Disposition");
+ }
+
+ public RawHeaders getRawHeaders() {
+ return mHeaders;
+ }
+
+ public String getContentType() {
+ return mHeaders.get("Content-Type");
+ }
+
+ public String getFilename() {
+ String file = mContentDisposition.get("filename");
+ if (file == null)
+ return null;
+ return new File(file).getName();
+ }
+
+ public boolean isFile() {
+ return mContentDisposition.containsKey("filename");
+ }
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
index 14cbc84..cd9306b 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
@@ -28,120 +28,127 @@ import com.koushikdutta.async.http.AsyncHttpPost;
import com.koushikdutta.async.http.libcore.RawHeaders;
public class AsyncHttpServer implements CompletedEmitter {
- AsyncServerSocket mListener;
+ ArrayList<AsyncServerSocket> mListeners = new ArrayList<AsyncServerSocket>();
public void stop() {
- if (mListener != null)
- mListener.stop();
+ if (mListeners != null) {
+ for (AsyncServerSocket listener: mListeners) {
+ listener.stop();
+ }
+ }
}
- public AsyncHttpServer(AsyncServer server, int port) {
- server.listen(null, port, new ListenCallback() {
- @Override
- public void onAccepted(final AsyncSocket socket) {
- AsyncHttpServerRequestImpl req = new AsyncHttpServerRequestImpl() {
- Pair match;
- boolean responseComplete;
- boolean requestComplete;
- AsyncHttpServerResponseImpl res;
- boolean hasContinued;
- @Override
- protected void onHeadersReceived() {
- RawHeaders headers = getRawHeaders();
+ ListenCallback mListenCallback = new ListenCallback() {
+ @Override
+ public void onAccepted(final AsyncSocket socket) {
+ AsyncHttpServerRequestImpl req = new AsyncHttpServerRequestImpl() {
+ Pair match;
+ boolean responseComplete;
+ boolean requestComplete;
+ AsyncHttpServerResponseImpl res;
+ boolean hasContinued;
+ @Override
+ protected void onHeadersReceived() {
+ RawHeaders headers = getRawHeaders();
- // should the negotiation of 100 continue be here, or in the request impl?
- // probably here, so AsyncResponse can negotiate a 100 continue.
- if (!hasContinued && "100-continue".equals(headers.get("Expect"))) {
-// System.out.println("continuing...");
- Util.writeAll(mSocket, "HTTP/1.1 100 Continue\r\n".getBytes(), new CompletedCallback() {
- @Override
- public void onCompleted(Exception ex) {
- if (ex != null) {
- report(ex);
- return;
- }
- hasContinued = true;
- onHeadersReceived();
+ // should the negotiation of 100 continue be here, or in the request impl?
+ // probably here, so AsyncResponse can negotiate a 100 continue.
+ if (!hasContinued && "100-continue".equals(headers.get("Expect"))) {
+ pause();
+// System.out.println("continuing...");
+ Util.writeAll(mSocket, "HTTP/1.1 100 Continue\r\n".getBytes(), new CompletedCallback() {
+ @Override
+ public void onCompleted(Exception ex) {
+ resume();
+ if (ex != null) {
+ report(ex);
+ return;
}
- });
- return;
- }
-// System.out.println(headers.toHeaderString());
-
- String statusLine = headers.getStatusLine();
- String[] parts = statusLine.split(" ");
- String path = parts[1];
- path = path.split("\\?")[0];
- String action = parts[0];
- synchronized (mActions) {
- ArrayList<Pair> pairs = mActions.get(action);
- if (pairs != null) {
- for (Pair p: pairs) {
- Matcher m = p.regex.matcher(path);
- if (m.matches()) {
- mMatcher = m;
- match = p;
- break;
- }
+ hasContinued = true;
+ onHeadersReceived();
+ }
+ });
+ return;
+ }
+// System.out.println(headers.toHeaderString());
+
+ String statusLine = headers.getStatusLine();
+ String[] parts = statusLine.split(" ");
+ String path = parts[1];
+ path = path.split("\\?")[0];
+ String action = parts[0];
+ synchronized (mActions) {
+ ArrayList<Pair> pairs = mActions.get(action);
+ if (pairs != null) {
+ for (Pair p: pairs) {
+ Matcher m = p.regex.matcher(path);
+ if (m.matches()) {
+ mMatcher = m;
+ match = p;
+ break;
}
}
}
- res = new AsyncHttpServerResponseImpl(socket) {
- @Override
- protected void onCompleted() {
- responseComplete = true;
- // reuse the socket for a subsequent request.
- handleOnCompleted();
- }
- };
- if (match == null) {
- res.responseCode(404);
- res.end();
- return;
+ }
+ res = new AsyncHttpServerResponseImpl(socket) {
+ @Override
+ protected void onEnd() {
+ responseComplete = true;
+ // reuse the socket for a subsequent request.
+ handleOnCompleted();
}
+ };
+ if (match == null) {
+ res.responseCode(404);
+ res.end();
+ return;
+ }
- if (!getBody().readFullyOnRequest()) {
-// Assert.assertTrue(getBody() instanceof CompletedEmitter);
-// CompletedEmitter completed = (CompletedEmitter)getBody();
-// completed.setCompletedCallback(this);
- match.callback.onRequest(this, res);
- }
- else if (requestComplete) {
- match.callback.onRequest(this, res);
- }
+ if (!getBody().readFullyOnRequest()) {
+// Assert.assertTrue(getBody() instanceof CompletedEmitter);
+// CompletedEmitter completed = (CompletedEmitter)getBody();
+// completed.setCompletedCallback(this);
+ match.callback.onRequest(this, res);
+ }
+ else if (requestComplete) {
+ match.callback.onRequest(this, res);
}
+ }
- @Override
- public void onCompleted(Exception e) {
- requestComplete = true;
- super.onCompleted(e);
- mSocket.setDataCallback(null);
- mSocket.pause();
- handleOnCompleted();
+ @Override
+ public void onCompleted(Exception e) {
+ requestComplete = true;
+ super.onCompleted(e);
+ mSocket.setDataCallback(null);
+ mSocket.pause();
+ handleOnCompleted();
- if (getBody().readFullyOnRequest()) {
- match.callback.onRequest(this, res);
- }
+ if (getBody().readFullyOnRequest()) {
+ match.callback.onRequest(this, res);
}
-
- private void handleOnCompleted() {
- if (requestComplete && responseComplete) {
- onAccepted(socket);
- }
+ }
+
+ private void handleOnCompleted() {
+ if (requestComplete && responseComplete) {
+ onAccepted(socket);
}
- };
- req.setSocket(socket);
- socket.resume();
- }
+ }
+ };
+ req.setSocket(socket);
+ socket.resume();
+ }
- @Override
- public void onCompleted(Exception error) {
- report(error);
- }
+ @Override
+ public void onCompleted(Exception error) {
+ report(error);
+ }
- @Override
- public void onListening(AsyncServerSocket socket) {
- mListener = socket;
- }
- });
+ @Override
+ public void onListening(AsyncServerSocket socket) {
+ mListeners.add(socket);
+ }
+ };
+
+ public void listen(AsyncServer server, int port) {
+ server.listen(null, port, mListenCallback);
}
private void report(Exception ex) {
@@ -149,8 +156,12 @@ public class AsyncHttpServer implements CompletedEmitter {
mCompletedCallback.onCompleted(ex);
}
- public AsyncHttpServer(int port) {
- this(AsyncServer.getDefault(), port);
+ public void listen(int port) {
+ listen(AsyncServer.getDefault(), port);
+ }
+
+ public ListenCallback getListenCallback() {
+ return mListenCallback;
}
CompletedCallback mCompletedCallback;
@@ -206,9 +217,7 @@ public class AsyncHttpServer implements CompletedEmitter {
response.end();
return;
}
- AsyncHttpServerRequestImpl impl = (AsyncHttpServerRequestImpl)request;
-
- callback.onConnected(new WebSocketImpl(impl, response));
+ callback.onConnected(new WebSocketImpl(request, response));
}
});
}
@@ -242,6 +251,7 @@ public class AsyncHttpServer implements CompletedEmitter {
static Hashtable<String, String> mContentTypes = new Hashtable<String, String>();
{
mContentTypes.put("js", "application/javascript");
+ mContentTypes.put("json", "application/json");
mContentTypes.put("png", "image/png");
mContentTypes.put("jpg", "image/jpeg");
mContentTypes.put("html", "text/html");
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java
index 17ade33..2dce8e1 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java
@@ -2,12 +2,15 @@ package com.koushikdutta.async.http.server;
import java.util.regex.Matcher;
+import com.koushikdutta.async.AsyncSocket;
+import com.koushikdutta.async.CompletedEmitter;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.http.AsyncHttpRequestBody;
import com.koushikdutta.async.http.libcore.RequestHeaders;
-public interface AsyncHttpServerRequest extends DataEmitter {
+public interface AsyncHttpServerRequest extends DataEmitter, CompletedEmitter {
public RequestHeaders getHeaders();
public Matcher getMatcher();
public AsyncHttpRequestBody getBody();
+ public AsyncSocket getSocket();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
index 2fb081a..1cd3f86 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
@@ -17,6 +17,17 @@ public abstract class AsyncHttpServerRequestImpl implements AsyncHttpServerReque
AsyncSocket mSocket;
Matcher mMatcher;
+ private CompletedCallback mCompleted;
+ @Override
+ public void setCompletedCallback(CompletedCallback callback) {
+ mCompleted = callback;
+ }
+
+ @Override
+ public CompletedCallback getCompletedCallback() {
+ return mCompleted;
+ }
+
private CompletedCallback mReporter = new CompletedCallback() {
@Override
public void onCompleted(Exception error) {
@@ -29,6 +40,8 @@ public abstract class AsyncHttpServerRequestImpl implements AsyncHttpServerReque
public void onCompleted(Exception e) {
if (mBody != null)
mBody.onCompleted(e);
+ if (mCompleted != null)
+ mCompleted.onCompleted(e);
}
abstract protected void onHeadersReceived();
@@ -76,6 +89,11 @@ public abstract class AsyncHttpServerRequestImpl implements AsyncHttpServerReque
LineEmitter liner = new LineEmitter(mSocket);
liner.setLineCallback(mHeaderCallback);
}
+
+ @Override
+ public AsyncSocket getSocket() {
+ return mSocket;
+ }
private RequestHeaders mHeaders = new RequestHeaders(null, mRawHeaders);
@Override
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java
index 49e97b0..5430895 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java
@@ -5,9 +5,10 @@ import java.io.File;
import org.json.JSONObject;
import com.koushikdutta.async.DataSink;
+import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
-public interface AsyncHttpServerResponse extends DataSink {
+public interface AsyncHttpServerResponse extends DataSink, CompletedCallback {
public void end();
public void send(String contentType, String string);
public void send(String string);
@@ -18,4 +19,8 @@ public interface AsyncHttpServerResponse extends DataSink {
public void writeHead();
public void setContentType(String contentType);
public void redirect(String location);
+ /**
+ * Alias for end. Used with CompletedEmitters
+ */
+ public void onCompleted(Exception ex);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
index e270978..5aea616 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
@@ -66,7 +66,7 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
}
private void writeInternal(ByteBufferList bb) {
- Assert.assertTrue(!mCompleted);
+ Assert.assertTrue(!mEnded);
initFirstWrite();
mChunker.write(bb);
}
@@ -94,11 +94,11 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
public void end() {
if (null == mRawHeaders.get("Transfer-Encoding")) {
send("text/html", "");
- onCompleted();
+ onEnd();
return;
}
writeInternal(ByteBuffer.wrap(new byte[0]));
- onCompleted();
+ onEnd();
}
private boolean mHeadWritten = false;
@@ -127,16 +127,16 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
writeHead();
mSink.write(ByteBuffer.wrap(string.getBytes()));
- onCompleted();
+ onEnd();
}
catch (UnsupportedEncodingException e) {
Assert.fail();
}
}
- boolean mCompleted;
- protected void onCompleted() {
- mCompleted = true;
+ boolean mEnded;
+ protected void onEnd() {
+ mEnded = true;
}
protected void report(Exception e) {
@@ -184,4 +184,12 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
mRawHeaders.set("Location", location);
end();
}
+
+ @Override
+ public void onCompleted(Exception ex) {
+ if (ex != null) {
+ ex.printStackTrace();
+ }
+ end();
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java b/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
index 60b7104..e9607dd 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
@@ -1,7 +1,6 @@
package com.koushikdutta.async.http.server;
import java.nio.ByteBuffer;
-import java.util.DuplicateFormatFlagsException;
import junit.framework.Assert;
@@ -49,9 +48,9 @@ public class BoundaryEmitter extends FilteredDataCallback {
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
// System.out.println(bb.getString());
- System.out.println("chunk: " + bb.remaining());
+// System.out.println("chunk: " + bb.remaining());
- System.out.println("state: " + state);
+// System.out.println("state: " + state);
// if we were in the middle of a potential match, let's throw that
// at the beginning of the buffer and process it too.
@@ -92,7 +91,7 @@ public class BoundaryEmitter extends FilteredDataCallback {
// len can be -1 on the first boundary
Assert.assertEquals(-2, len);
}
- System.out.println("bstart");
+// System.out.println("bstart");
onBoundaryStart();
}
else if (buf[i] == '-') {
@@ -119,7 +118,7 @@ public class BoundaryEmitter extends FilteredDataCallback {
ByteBufferList list = new ByteBufferList();
list.add(b);
super.onDataAvailable(emitter, list);
- System.out.println("bend");
+// System.out.println("bend");
onBoundaryEnd();
}
else {
@@ -153,8 +152,8 @@ public class BoundaryEmitter extends FilteredDataCallback {
}
if (last < buf.length) {
- System.out.println("amount left at boundary: " + (buf.length - last));
- System.out.println(state);
+// System.out.println("amount left at boundary: " + (buf.length - last));
+// System.out.println(state);
int keep = Math.max(state, 0);
ByteBuffer b = ByteBuffer.wrap(buf, last, buf.length - last - keep);
ByteBufferList list = new ByteBufferList();
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/WebSocketImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/WebSocketImpl.java
index b4e0d1b..af463d0 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/WebSocketImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/WebSocketImpl.java
@@ -27,8 +27,8 @@ public class WebSocketImpl implements WebSocket {
private AsyncSocket mSocket;
BufferedDataSink mSink;
- public WebSocketImpl(AsyncHttpServerRequestImpl request, AsyncHttpServerResponse response) {
- mSocket = request.mSocket;
+ public WebSocketImpl(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
+ mSocket = request.getSocket();
mSink = new BufferedDataSink(mSocket);
mSocket.setClosedCallback(new ClosedCallback() {
diff --git a/AndroidAsync/src/com/koushikdutta/test/TestActivity.java b/AndroidAsync/src/com/koushikdutta/test/TestActivity.java
index a93036f..89be215 100644
--- a/AndroidAsync/src/com/koushikdutta/test/TestActivity.java
+++ b/AndroidAsync/src/com/koushikdutta/test/TestActivity.java
@@ -84,7 +84,8 @@ public class TestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- AsyncHttpServer server = new AsyncHttpServer(3000);
+ AsyncHttpServer server = new AsyncHttpServer();
+ server.listen(3000);
server.get("/", new HttpServerRequestCallback() {
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
diff --git a/AndroidAsyncSample/gen/com/koushikdutta/async/R.java b/AndroidAsyncSample/gen/com/koushikdutta/async/R.java
index 48d7fcd..07e6084 100644
--- a/AndroidAsyncSample/gen/com/koushikdutta/async/R.java
+++ b/AndroidAsyncSample/gen/com/koushikdutta/async/R.java
@@ -4,38 +4,11 @@
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
-
package com.koushikdutta.async;
public final class R {
- public static final class attr {
- }
- public static final class drawable {
- public static final int ic_action_search=0x7f020000;
- public static final int ic_launcher=0x7f020001;
- }
- public static final class id {
- public static final int chart=0x7f070004;
- public static final int desksms=0x7f070002;
- public static final int go=0x7f070000;
- public static final int menu_settings=0x7f070005;
- public static final int rommanager=0x7f070001;
- public static final int tether=0x7f070003;
- }
- public static final class layout {
- public static final int activity_main=0x7f030000;
- }
- public static final class menu {
- public static final int activity_main=0x7f060000;
- }
- public static final class string {
- public static final int app_name=0x7f040000;
- public static final int download=0x7f040004;
- public static final int hello_world=0x7f040001;
- public static final int menu_settings=0x7f040002;
- public static final int title_activity_main=0x7f040003;
- }
- public static final class style {
- public static final int AppTheme=0x7f050000;
- }
+ public static final class drawable {
+ public static final int ic_launcher = 0x7f020001;
+ public static final int ic_action_search = 0x7f020000;
+ }
}
diff --git a/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java b/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
index a335726..f9f1a0e 100644
--- a/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
+++ b/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
@@ -21,6 +21,10 @@ import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpPost;
import com.koushikdutta.async.http.AsyncHttpResponse;
import com.koushikdutta.async.http.UrlEncodedFormBody;
+import com.koushikdutta.async.http.server.AsyncHttpServer;
+import com.koushikdutta.async.http.server.WebSocket;
+import com.koushikdutta.async.http.server.WebSocket.StringCallback;
+import com.koushikdutta.async.http.server.WebSocketCallback;
public class MainActivity extends Activity {
ImageView rommanager;
@@ -45,7 +49,21 @@ public class MainActivity extends Activity {
tether = (ImageView)findViewById(R.id.tether);
desksms = (ImageView)findViewById(R.id.desksms);
chart = (ImageView)findViewById(R.id.chart);
+
+ server.listen(4500);
+ server.websocket("/", new WebSocketCallback() {
+ @Override
+ public void onConnected(WebSocket webSocket) {
+ webSocket.setStringCallback(new StringCallback() {
+ @Override
+ public void onStringAvailable(String s) {
+ System.out.println("String: " + s);
+ }
+ });
+ }
+ });
}
+ AsyncHttpServer server = new AsyncHttpServer();
@Override
public boolean onCreateOptionsMenu(Menu menu) {