aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcretin45 <cretin45@gmail.com>2014-09-09 12:13:07 -0700
committercretin45 <cretin45@gmail.com>2014-09-09 14:26:09 -0700
commit2ac87dd1859f3ca4b7bb7709c5d24091d6d889f3 (patch)
treeb09221245098c938ca99cf021ba15dd89032985e
parentd7c7470a2599a6f76b7f92ed8015b0ec1b1e45c2 (diff)
parent0b99866b2b74a37a419183e1ff4b1c59974cfa8d (diff)
downloadAndroidAsync-2ac87dd1859f3ca4b7bb7709c5d24091d6d889f3.tar.gz
AndroidAsync-2ac87dd1859f3ca4b7bb7709c5d24091d6d889f3.tar.bz2
AndroidAsync-2ac87dd1859f3ca4b7bb7709c5d24091d6d889f3.zip
Merge upstream into cm-11.0
Change-Id: I304cfea73e62d7a78d4eb1e0a766d6bb1666476f
-rw-r--r--.gitignore6
-rw-r--r--AndroidAsync/Android.mk1
-rw-r--r--AndroidAsync/AndroidAsync-AndroidAsync.iml88
-rw-r--r--AndroidAsync/AndroidAsync.iml3
-rw-r--r--AndroidAsync/AndroidManifest.xml11
-rw-r--r--AndroidAsync/build.gradle44
-rw-r--r--AndroidAsync/project.properties2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java20
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java3
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java236
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncServer.java19
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/BufferedDataEmitter.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java9
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java140
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/DataEmitter.java1
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/PushParser.java3
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java8
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/future/ConvertFuture.java13
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java40
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/future/SimpleFuture.java13
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java63
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java28
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java1
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java28
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLEngineConfigurator.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java61
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java15
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/Multimap.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java155
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java9
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java27
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/body/MultipartFormDataBody.java13
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/body/Part.java6
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/body/UrlEncodedFormBody.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/filter/GZIPInputFilter.java9
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/libcore/RequestHeaders.java4
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/libcore/StrictLineReader.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java20
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java6
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/socketio/SocketIOClient.java3
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/stream/InputStreamDataEmitter.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java51
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/util/Allocator.java48
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/util/Charsets.java (renamed from AndroidAsync/src/com/koushikdutta/async/http/libcore/Charsets.java)2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/util/FileCache.java43
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/util/StreamUtility.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/util/UntypedHashtable.java26
-rw-r--r--AndroidAsync/test/assets/6691924d7d24237d3b3679310157d640 (renamed from AndroidAsyncTest/testdata/6691924d7d24237d3b3679310157d640)bin100000 -> 100000 bytes
-rw-r--r--AndroidAsync/test/assets/hello.txt (renamed from AndroidAsyncTest/testdata/hello.txt)0
-rw-r--r--AndroidAsync/test/assets/test.json (renamed from AndroidAsyncTest/testdata/test.json)0
-rw-r--r--AndroidAsync/test/res/drawable-hdpi/ic_launcher.png (renamed from AndroidAsyncTest/res/drawable-hdpi/ic_launcher.png)bin9397 -> 9397 bytes
-rw-r--r--AndroidAsync/test/res/drawable-ldpi/ic_launcher.png (renamed from AndroidAsyncTest/res/drawable-ldpi/ic_launcher.png)bin2729 -> 2729 bytes
-rw-r--r--AndroidAsync/test/res/drawable-mdpi/ic_launcher.png (renamed from AndroidAsyncTest/res/drawable-mdpi/ic_launcher.png)bin5237 -> 5237 bytes
-rw-r--r--AndroidAsync/test/res/drawable-xhdpi/ic_launcher.png (renamed from AndroidAsyncTest/res/drawable-xhdpi/ic_launcher.png)bin14383 -> 14383 bytes
-rw-r--r--AndroidAsync/test/res/raw/keystore.bks (renamed from AndroidAsyncTest/res/raw/keystore.bks)bin2221 -> 2221 bytes
-rw-r--r--AndroidAsync/test/res/values/strings.xml (renamed from AndroidAsyncTest/res/values/strings.xml)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/BodyTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/BodyTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/ByteUtilTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/ByteUtilTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/CacheTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/CacheTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/DnsTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/DnsTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/FileCacheTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/FileCacheTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/FileTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/FileTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/FutureTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/FutureTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/HttpClientTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/HttpClientTests.java)38
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/HttpServerTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/Issue59.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/Issue59.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/Md5.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/Md5.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/MultipartTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/MultipartTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/ParserTests.java56
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/ProxyTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/ProxyTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/RedirectTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/RedirectTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/SSLTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/SSLTests.java)1
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/SanityChecks.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/SanityChecks.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/SocketIOTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/SocketIOTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/TimeoutTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/TimeoutTests.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/TriggerFuture.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/TriggerFuture.java)0
-rw-r--r--AndroidAsync/test/src/com/koushikdutta/async/test/WebSocketTests.java (renamed from AndroidAsyncTest/src/com/koushikdutta/async/test/WebSocketTests.java)0
-rw-r--r--AndroidAsyncTest/.classpath10
-rw-r--r--AndroidAsyncTest/.project34
-rw-r--r--AndroidAsyncTest/AndroidAsyncTest.iml27
-rw-r--r--AndroidAsyncTest/AndroidManifest.xml25
-rw-r--r--AndroidAsyncTest/proguard-project.txt20
-rw-r--r--AndroidAsyncTest/project.properties15
-rw-r--r--README.md2
91 files changed, 959 insertions, 610 deletions
diff --git a/.gitignore b/.gitignore
index 3070adf..30c8bb1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,9 @@ local.properties
gen
.gradle
build
+.idea/
+.DS_Store
+
+okhttp
+okio
+libs
diff --git a/AndroidAsync/Android.mk b/AndroidAsync/Android.mk
index bf03dcb..e32c65c 100644
--- a/AndroidAsync/Android.mk
+++ b/AndroidAsync/Android.mk
@@ -19,7 +19,6 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := AndroidAsync
-LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(call all-java-files-under, src)
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/AndroidAsync/AndroidAsync-AndroidAsync.iml b/AndroidAsync/AndroidAsync-AndroidAsync.iml
new file mode 100644
index 0000000..e506543
--- /dev/null
+++ b/AndroidAsync/AndroidAsync-AndroidAsync.iml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="Gradle.AndroidAsync" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":AndroidAsync:AndroidAsync" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" />
+ <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
+ <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
+ <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" />
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ <option name="LIBRARY_PROJECT" value="true" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/test/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/test/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/test/src" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/libs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/poms" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/AndroidAsync/AndroidAsync.iml b/AndroidAsync/AndroidAsync.iml
index 8c69f52..edb7738 100644
--- a/AndroidAsync/AndroidAsync.iml
+++ b/AndroidAsync/AndroidAsync.iml
@@ -4,6 +4,9 @@
<facet type="android" name="Android">
<configuration>
<option name="LIBRARY_PROJECT" value="true" />
+ <proGuardCfgFiles>
+ <file>file://$APPLICATION_HOME_DIR$/sdk/tools/proguard/proguard-android.txt</file>
+ </proGuardCfgFiles>
<option name="UPDATE_PROPERTY_FILES" value="true" />
<notImportedProperties>
<property>MANIFEST_FILE_PATH</property>
diff --git a/AndroidAsync/AndroidManifest.xml b/AndroidAsync/AndroidManifest.xml
index 4496f74..ae615c1 100644
--- a/AndroidAsync/AndroidManifest.xml
+++ b/AndroidAsync/AndroidManifest.xml
@@ -1,15 +1,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.koushikdutta.async"
- android:versionCode="125"
- android:versionName="1.2.5" >
+ android:versionCode="138"
+ android:versionName="1.3.8">
<uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="18" />
+ tools:node="replace" />
<uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.READ_LOGS"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application>
</application>
diff --git a/AndroidAsync/build.gradle b/AndroidAsync/build.gradle
index 9f7f19d..0a1985d 100644
--- a/AndroidAsync/build.gradle
+++ b/AndroidAsync/build.gradle
@@ -3,36 +3,42 @@ buildscript {
maven { url 'http://repo1.maven.org/maven2' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.10.+'
+ classpath 'com.android.tools.build:gradle:+'
}
}
-apply plugin: 'android-library'
-
-dependencies {
- compile 'com.android.support:support-v4:13.0.0'
-}
+apply plugin: 'com.android.library'
android {
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
-
- java {
- srcDir 'src/'
- }
- }
- }
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
- compileSdkVersion 19
- buildToolsVersion "19.0.3"
+ jniLibs.srcDirs = ['libs/']
+
+ java.srcDirs=['src/'
+// , '../conscrypt/'
+// , '../compat/'
+ ]
+ }
+ androidTest.java.srcDirs=['test/src/']
+ androidTest.res.srcDirs=['test/res/']
+ androidTest.assets.srcDirs=['test/assets/']
+ }
+
+ lintOptions {
+ abortOnError false
+ }
defaultConfig {
- minSdkVersion 7
+ minSdkVersion 9
targetSdkVersion 19
}
+
+ compileSdkVersion 19
+ buildToolsVersion "20.0.0"
}
// upload to maven task
if (System.getenv().I_AM_KOUSH == 'true') {
- apply from: 'https://raw.github.com/koush/mvn-repo/master/maven.gradle'
+ apply from: 'https://raw.githubusercontent.com/koush/mvn-repo/master/maven.gradle'
}
diff --git a/AndroidAsync/project.properties b/AndroidAsync/project.properties
index 91d2b02..edc832b 100644
--- a/AndroidAsync/project.properties
+++ b/AndroidAsync/project.properties
@@ -13,3 +13,5 @@
# Project target.
target=android-19
android.library=true
+
+
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java b/AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java
index 2677960..19fd2c3 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncNetworkSocket.java
@@ -5,6 +5,7 @@ import android.util.Log;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
+import com.koushikdutta.async.util.Allocator;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -29,7 +30,7 @@ public class AsyncNetworkSocket implements AsyncSocket {
InetSocketAddress socketAddress;
void attach(SocketChannel channel, InetSocketAddress socketAddress) throws IOException {
this.socketAddress = socketAddress;
- maxAlloc = 256 * 1024; // 256K
+ allocator = new Allocator();
mChannel = new SocketChannelWrapper(channel);
}
@@ -37,7 +38,7 @@ public class AsyncNetworkSocket implements AsyncSocket {
mChannel = new DatagramChannelWrapper(channel);
// keep udp at roughly the mtu, which is 1540 or something
// letting it grow freaks out nio apparently.
- maxAlloc = 8192;
+ allocator = new Allocator(8192);
}
ChannelWrapper getChannel() {
@@ -136,8 +137,7 @@ public class AsyncNetworkSocket implements AsyncSocket {
private ByteBufferList pending = new ByteBufferList();
// private ByteBuffer[] buffers = new ByteBuffer[8];
- int maxAlloc;
- int mToAlloc = 0;
+ Allocator allocator;
int onReadable() {
spitPending();
// even if the socket is paused,
@@ -150,7 +150,7 @@ public class AsyncNetworkSocket implements AsyncSocket {
boolean closed = false;
// ByteBufferList.obtainArray(buffers, Math.min(Math.max(mToAlloc, 2 << 11), maxAlloc));
- ByteBuffer b = ByteBufferList.obtain(Math.min(Math.max(mToAlloc, 2 << 11), maxAlloc));
+ ByteBuffer b = allocator.allocate();
// keep track of the max mount read during this read cycle
// so we can be quicker about allocations during the next
// time this socket reads.
@@ -163,7 +163,7 @@ public class AsyncNetworkSocket implements AsyncSocket {
total += read;
}
if (read > 0) {
- mToAlloc = (int)read * 2;
+ allocator.track(read);
b.flip();
// for (int i = 0; i < buffers.length; i++) {
// ByteBuffer b = buffers[i];
@@ -174,6 +174,9 @@ public class AsyncNetworkSocket implements AsyncSocket {
pending.add(b);
Util.emitAllData(this, pending);
}
+ else {
+ ByteBufferList.reclaim(b);
+ }
if (closed) {
reportEndPending(null);
@@ -361,4 +364,9 @@ public class AsyncNetworkSocket implements AsyncSocket {
public Object getSocket() {
return getChannel().getSocket();
}
+
+ @Override
+ public String charset() {
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
index e45d9c0..ba52642 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
@@ -2,6 +2,9 @@ package com.koushikdutta.async;
import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLEngine;
+
public interface AsyncSSLSocket extends AsyncSocket {
public X509Certificate[] getPeerCertificates();
+ public SSLEngine getSSLEngine();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
index ff45a61..0c53f56 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocketWrapper.java
@@ -5,6 +5,7 @@ import android.os.Build;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
+import com.koushikdutta.async.util.Allocator;
import com.koushikdutta.async.wrapper.AsyncSocketWrapper;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
@@ -27,40 +28,103 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket {
+ public interface HandshakeCallback {
+ public void onHandshakeCompleted(Exception e, AsyncSSLSocket socket);
+ }
+
+ static SSLContext defaultSSLContext;
+
AsyncSocket mSocket;
BufferedDataEmitter mEmitter;
BufferedDataSink mSink;
- ByteBuffer mReadTmp = ByteBufferList.obtain(8192);
- boolean mUnwrapping = false;
+ boolean mUnwrapping;
+ SSLEngine engine;
+ boolean finishedHandshake;
+ private int mPort;
+ private String mHost;
+ private boolean mWrapping;
HostnameVerifier hostnameVerifier;
+ HandshakeCallback handshakeCallback;
+ X509Certificate[] peerCertificates;
+ WritableCallback mWriteableCallback;
+ DataCallback mDataCallback;
+ TrustManager[] trustManagers;
+ boolean clientMode;
- @Override
- public void end() {
- mSocket.end();
+ static {
+ // following is the "trust the system" certs setup
+ try {
+ // critical extension 2.5.29.15 is implemented improperly prior to 4.0.3.
+ // https://code.google.com/p/android/issues/detail?id=9307
+ // https://groups.google.com/forum/?fromgroups=#!topic/netty/UCfqPPk5O4s
+ // certs that use this extension will throw in Cipher.java.
+ // fallback is to use a custom SSLContext, and hack around the x509 extension.
+ if (Build.VERSION.SDK_INT <= 15)
+ throw new Exception();
+ defaultSSLContext = SSLContext.getInstance("Default");
+ }
+ catch (Exception ex) {
+ try {
+ defaultSSLContext = SSLContext.getInstance("TLS");
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+ for (X509Certificate cert : certs) {
+ if (cert != null && cert.getCriticalExtensionOIDs() != null)
+ cert.getCriticalExtensionOIDs().remove("2.5.29.15");
+ }
+ }
+ } };
+ defaultSSLContext.init(null, trustAllCerts, null);
+ }
+ catch (Exception ex2) {
+ ex.printStackTrace();
+ ex2.printStackTrace();
+ }
+ }
}
- public AsyncSSLSocketWrapper(AsyncSocket socket, String host, int port) {
- this(socket, host, port, sslContext, null, null, true);
+ public static SSLContext getDefaultSSLContext() {
+ return defaultSSLContext;
}
- TrustManager[] trustManagers;
- boolean clientMode;
+ public static void handshake(AsyncSocket socket,
+ String host, int port,
+ SSLEngine sslEngine,
+ TrustManager[] trustManagers, HostnameVerifier verifier, boolean clientMode,
+ final HandshakeCallback callback) {
+ AsyncSSLSocketWrapper wrapper = new AsyncSSLSocketWrapper(socket, host, port, sslEngine, trustManagers, verifier, clientMode);
+ wrapper.handshakeCallback = callback;
+ socket.setClosedCallback(new CompletedCallback() {
+ @Override
+ public void onCompleted(Exception ex) {
+ callback.onHandshakeCompleted(new SSLException(ex), null);
+ }
+ });
+ try {
+ wrapper.engine.beginHandshake();
+ wrapper.handleHandshakeStatus(wrapper.engine.getHandshakeStatus());
+ } catch (SSLException e) {
+ wrapper.report(e);
+ }
+ }
- public AsyncSSLSocketWrapper(AsyncSocket socket, String host, int port, SSLContext sslContext, TrustManager[] trustManagers, HostnameVerifier verifier, boolean clientMode) {
+ private AsyncSSLSocketWrapper(AsyncSocket socket,
+ String host, int port,
+ SSLEngine sslEngine,
+ TrustManager[] trustManagers, HostnameVerifier verifier, boolean clientMode) {
mSocket = socket;
hostnameVerifier = verifier;
this.clientMode = clientMode;
this.trustManagers = trustManagers;
+ this.engine = sslEngine;
- if (sslContext == null)
- sslContext = AsyncSSLSocketWrapper.sslContext;
-
- if (host != null) {
- engine = sslContext.createSSLEngine(host, port);
- }
- else {
- engine = sslContext.createSSLEngine();
- }
mHost = host;
mPort = port;
engine.setUseClientMode(clientMode);
@@ -77,6 +141,8 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
// aka exhcange.setDatacallback
mEmitter = new BufferedDataEmitter(socket);
+ final Allocator allocator = new Allocator();
+ allocator.setMinAlloc(8192);
final ByteBufferList transformed = new ByteBufferList();
mEmitter.setDataCallback(new DataCallback() {
@Override
@@ -86,8 +152,10 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
try {
mUnwrapping = true;
- mReadTmp.position(0);
- mReadTmp.limit(mReadTmp.capacity());
+ if (bb.hasRemaining()) {
+ ByteBuffer all = bb.getAll();
+ bb.add(all);
+ }
ByteBuffer b = ByteBufferList.EMPTY_BYTEBUFFER;
while (true) {
@@ -95,11 +163,18 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
b = bb.remove();
}
int remaining = b.remaining();
-
- SSLEngineResult res = engine.unwrap(b, mReadTmp);
+ int before = transformed.remaining();
+
+ SSLEngineResult res;
+ {
+ // wrap to prevent access to the readBuf
+ ByteBuffer readBuf = allocator.allocate();
+ res = engine.unwrap(b, readBuf);
+ addToPending(transformed, readBuf);
+ allocator.track(transformed.remaining() - before);
+ }
if (res.getStatus() == Status.BUFFER_OVERFLOW) {
- addToPending(transformed);
- mReadTmp = ByteBufferList.obtain(mReadTmp.remaining() * 2);
+ allocator.setMinAlloc(allocator.getMinAlloc() * 2);
remaining = -1;
}
else if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
@@ -113,14 +188,13 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
bb.addFirst(b);
b = ByteBufferList.EMPTY_BYTEBUFFER;
}
- handleResult(res);
- if (b.remaining() == remaining) {
+ handleHandshakeStatus(res.getHandshakeStatus());
+ if (b.remaining() == remaining && before == transformed.remaining()) {
bb.addFirst(b);
break;
}
}
- addToPending(transformed);
Util.emitAllData(AsyncSSLSocketWrapper.this, transformed);
}
catch (SSLException ex) {
@@ -134,81 +208,46 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
});
}
- void addToPending(ByteBufferList out) {
- if (mReadTmp.position() > 0) {
- mReadTmp.flip();
- out.add(mReadTmp);
- mReadTmp = ByteBufferList.obtain(mReadTmp.capacity());
- }
+ @Override
+ public SSLEngine getSSLEngine() {
+ return engine;
}
- static SSLContext sslContext;
-
- static {
- // following is the "trust the system" certs setup
- try {
- // critical extension 2.5.29.15 is implemented improperly prior to 4.0.3.
- // https://code.google.com/p/android/issues/detail?id=9307
- // https://groups.google.com/forum/?fromgroups=#!topic/netty/UCfqPPk5O4s
- // certs that use this extension will throw in Cipher.java.
- // fallback is to use a custom SSLContext, and hack around the x509 extension.
- if (Build.VERSION.SDK_INT <= 15)
- throw new Exception();
- sslContext = SSLContext.getInstance("Default");
+ void addToPending(ByteBufferList out, ByteBuffer mReadTmp) {
+ mReadTmp.flip();
+ if (mReadTmp.hasRemaining()) {
+ out.add(mReadTmp);
}
- catch (Exception ex) {
- try {
- sslContext = SSLContext.getInstance("TLS");
- TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
- for (X509Certificate cert : certs) {
- if (cert != null && cert.getCriticalExtensionOIDs() != null)
- cert.getCriticalExtensionOIDs().remove("2.5.29.15");
- }
- }
- } };
- sslContext.init(null, trustAllCerts, null);
- }
- catch (Exception ex2) {
- ex.printStackTrace();
- ex2.printStackTrace();
- }
+ else {
+ ByteBufferList.reclaim(mReadTmp);
}
}
- SSLEngine engine;
- boolean finishedHandshake = false;
- private String mHost;
+ @Override
+ public void end() {
+ mSocket.end();
+ }
public String getHost() {
return mHost;
}
- private int mPort;
-
public int getPort() {
return mPort;
}
- private void handleResult(SSLEngineResult res) {
- if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ private void handleHandshakeStatus(HandshakeStatus status) {
+ if (status == HandshakeStatus.NEED_TASK) {
final Runnable task = engine.getDelegatedTask();
task.run();
}
- if (res.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) {
+ if (status == HandshakeStatus.NEED_WRAP) {
write(ByteBufferList.EMPTY_BYTEBUFFER);
}
- if (res.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) {
+ if (status == HandshakeStatus.NEED_UNWRAP) {
mEmitter.onDataAvailable();
}
@@ -255,6 +294,11 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
throw e;
}
}
+ else {
+ finishedHandshake = true;
+ }
+ handshakeCallback.onHandshakeCompleted(null, this);
+ handshakeCallback = null;
if (mWriteableCallback != null)
mWriteableCallback.onWriteable();
mEmitter.onDataAvailable();
@@ -278,7 +322,6 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
assert !mWriteTmp.hasRemaining();
}
- private boolean mWrapping = false;
int calculateAlloc(int remaining) {
// alloc 50% more than we need for writing
@@ -320,7 +363,7 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
else {
mWriteTmp = ByteBufferList.obtain(calculateAlloc(bb.remaining()));
}
- handleResult(res);
+ handleHandshakeStatus(res.getHandshakeStatus());
}
catch (SSLException e) {
report(e);
@@ -345,10 +388,8 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
// if the handshake is finished, don't send
// 0 bytes of data, since that makes the ssl connection die.
// it wraps a 0 byte package, and craps out.
- if (finishedHandshake && bb.remaining() == 0) {
- mWrapping = false;
- return;
- }
+ if (finishedHandshake && bb.remaining() == 0)
+ break;
remaining = bb.remaining();
try {
ByteBuffer[] arr = bb.getAllArray();
@@ -364,8 +405,8 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
}
else {
mWriteTmp = ByteBufferList.obtain(calculateAlloc(bb.remaining()));
+ handleHandshakeStatus(res.getHandshakeStatus());
}
- handleResult(res);
}
catch (SSLException e) {
report(e);
@@ -376,8 +417,6 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
mWrapping = false;
}
- WritableCallback mWriteableCallback;
-
@Override
public void setWriteableCallback(WritableCallback handler) {
mWriteableCallback = handler;
@@ -389,13 +428,21 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
}
private void report(Exception e) {
+ final HandshakeCallback hs = handshakeCallback;
+ if (hs != null) {
+ handshakeCallback = null;
+ mSocket.setDataCallback(new NullDataCallback());
+ mSocket.end();
+ mSocket.close();
+ hs.onHandshakeCompleted(e, null);
+ return;
+ }
+
CompletedCallback cb = getEndCallback();
if (cb != null)
cb.onCompleted(e);
}
- DataCallback mDataCallback;
-
@Override
public void setDataCallback(DataCallback callback) {
mDataCallback = callback;
@@ -471,10 +518,13 @@ public class AsyncSSLSocketWrapper implements AsyncSocketWrapper, AsyncSSLSocket
return mSocket;
}
- X509Certificate[] peerCertificates;
-
@Override
public X509Certificate[] getPeerCertificates() {
return peerCertificates;
}
+
+ @Override
+ public String charset() {
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java b/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
index b5dce58..be4a363 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncServer.java
@@ -126,7 +126,12 @@ public class AsyncServer {
synchronousWorkers.execute(new Runnable() {
@Override
public void run() {
- selector.wakeupOnce();
+ try {
+ selector.wakeupOnce();
+ }
+ catch (Exception e) {
+ Log.i(LOGTAG, "Selector Exception? L Preview?");
+ }
}
});
}
@@ -224,7 +229,9 @@ public class AsyncServer {
// Log.i(LOGTAG, "****AsyncServer is shutting down.****");
final SelectorWrapper currentSelector;
final Semaphore semaphore;
+ final boolean isAffinityThread;
synchronized (this) {
+ isAffinityThread = isAffinityThread();
currentSelector = mSelector;
if (currentSelector == null)
return;
@@ -251,7 +258,8 @@ public class AsyncServer {
mAffinity = null;
}
try {
- semaphore.acquire();
+ if (!isAffinityThread)
+ semaphore.acquire();
}
catch (Exception e) {
}
@@ -600,6 +608,10 @@ public class AsyncServer {
runLoop(server, selector, queue);
}
catch (ClosedSelectorException e) {
+ StreamUtility.closeQuietly(selector.getSelector());
+ }
+ catch (AsyncSelectorException e) {
+ StreamUtility.closeQuietly(selector.getSelector());
}
// see if we keep looping, this must be in a synchronized block since the queue is accessed.
synchronized (server) {
@@ -719,6 +731,9 @@ public class AsyncServer {
}
}
}
+ catch (NullPointerException e) {
+ throw new AsyncSelectorException(e);
+ }
catch (IOException e) {
throw new AsyncSelectorException(e);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/BufferedDataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/BufferedDataEmitter.java
index 7d238b4..5c88b31 100644
--- a/AndroidAsync/src/com/koushikdutta/async/BufferedDataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/BufferedDataEmitter.java
@@ -32,7 +32,7 @@ public class BufferedDataEmitter implements DataEmitter, DataCallback {
if (mDataCallback != null && !mPaused && mBuffers.remaining() > 0)
mDataCallback.onDataAvailable(this, mBuffers);
- if (mEnded && mBuffers.remaining() == 0)
+ if (mEnded && mBuffers.remaining() == 0 && mEndCallback != null)
mEndCallback.onCompleted(mEndException);
}
@@ -96,4 +96,9 @@ public class BufferedDataEmitter implements DataEmitter, DataCallback {
public AsyncServer getServer() {
return mEmitter.getServer();
}
+
+ @Override
+ public String charset() {
+ return mEmitter.charset();
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java b/AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java
index 096be5b..ed4f87f 100644
--- a/AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java
+++ b/AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java
@@ -36,8 +36,6 @@ public class BufferedDataSink implements DataSink {
if (mPendingWrites.remaining() == 0) {
if (endPending)
mDataSink.end();
- if (closePending)
- mDataSink.close();
}
}
if (!mPendingWrites.hasRemaining() && mWritable != null)
@@ -113,16 +111,11 @@ public class BufferedDataSink implements DataSink {
@Override
public boolean isOpen() {
- return !closePending && mDataSink.isOpen();
+ return mDataSink.isOpen();
}
- boolean closePending;
@Override
public void close() {
- if (mPendingWrites.hasRemaining()) {
- closePending = true;
- return;
- }
mDataSink.close();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java b/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
index 794b74e..fe5b50d 100644
--- a/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
+++ b/AndroidAsync/src/com/koushikdutta/async/ByteBufferList.java
@@ -1,15 +1,20 @@
package com.koushikdutta.async;
+import android.annotation.TargetApi;
+import android.os.Build;
import android.os.Looper;
-import java.nio.Buffer;
+import com.koushikdutta.async.util.Charsets;
+
+import java.io.IOException;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.util.ArrayList;
+import java.nio.charset.Charset;
import java.util.Comparator;
-import java.util.LinkedList;
import java.util.PriorityQueue;
+@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class ByteBufferList {
ArrayDeque<ByteBuffer> mBuffers = new ArrayDeque<ByteBuffer>();
@@ -44,9 +49,12 @@ public class ByteBufferList {
public byte[] getAllByteArray() {
// fast path to return the contents of the first and only byte buffer,
// if that's what we're looking for. avoids allocation.
- if (mBuffers.size() == 1 && mBuffers.peek().capacity() == remaining()) {
- remaining = 0;
- return mBuffers.remove().array();
+ if (mBuffers.size() == 1) {
+ ByteBuffer peek = mBuffers.peek();
+ if (peek.capacity() == remaining() && peek.isDirect()) {
+ remaining = 0;
+ return mBuffers.remove().array();
+ }
}
byte[] ret = new byte[remaining()];
@@ -75,7 +83,25 @@ public class ByteBufferList {
public boolean hasRemaining() {
return remaining() > 0;
}
-
+
+ public short peekShort() {
+ return read(2).duplicate().getShort();
+ }
+
+ public int peekInt() {
+ return read(4).duplicate().getInt();
+ }
+
+ public long peekLong() {
+ return read(8).duplicate().getLong();
+ }
+
+ public byte[] peekBytes(int size) {
+ byte[] ret = new byte[size];
+ read(size).duplicate().get(ret);
+ return ret;
+ }
+
public int getInt() {
int ret = read(4).getInt();
remaining -= 4;
@@ -203,46 +229,7 @@ public class ByteBufferList {
return first.order(order);
}
- ByteBuffer ret = null;
- int retOffset = 0;
- int allocSize = 0;
-
- // attempt to find a buffer that can fit this, and the necessary
- // alloc size to not leave anything leftover in the final buffer.
- for (ByteBuffer b: mBuffers) {
- if (allocSize >= count)
- break;
- // see if this fits...
- if ((ret == null || b.capacity() > ret.capacity()) && b.capacity() >= count) {
- ret = b;
- retOffset = allocSize;
- }
- allocSize += b.remaining();
- }
-
- if (ret != null && ret.capacity() > allocSize) {
- // move the current contents of the target bytebuffer around to its final position
- System.arraycopy(ret.array(), ret.arrayOffset() + ret.position(), ret.array(), ret.arrayOffset() + retOffset, ret.remaining());
- int retRemaining = ret.remaining();
- ret.position(0);
- ret.limit(allocSize);
- allocSize = 0;
- while (allocSize < count) {
- ByteBuffer b = mBuffers.remove();
- if (b != ret) {
- System.arraycopy(b.array(), b.arrayOffset() + b.position(), ret.array(), ret.arrayOffset() + allocSize, b.remaining());
- allocSize += b.remaining();
- reclaim(b);
- }
- else {
- allocSize += retRemaining;
- }
- }
- mBuffers.addFirst(ret);
- return ret.order(order);
- }
-
- ret = obtain(count);
+ ByteBuffer ret = obtain(count);
ret.limit(count);
byte[] bytes = ret.array();
int offset = 0;
@@ -346,24 +333,43 @@ public class ByteBufferList {
System.out.println(peekString());
}
- // not doing toString as this is really nasty in the debugger...
public String peekString() {
+ return peekString(null);
+ }
+
+ // not doing toString as this is really nasty in the debugger...
+ public String peekString(Charset charset) {
+ if (charset == null)
+ charset = Charsets.US_ASCII;
StringBuilder builder = new StringBuilder();
for (ByteBuffer bb: mBuffers) {
- builder.append(new String(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
+ byte[] bytes;
+ int offset;
+ int length;
+ if (bb.isDirect()) {
+ bytes = new byte[bb.remaining()];
+ offset = 0;
+ length = bb.remaining();
+ bb.get(bytes);
+ }
+ else {
+ bytes = bb.array();
+ offset = bb.arrayOffset() + bb.position();
+ length = bb.remaining();
+ }
+ builder.append(new String(bytes, offset, length, charset));
}
return builder.toString();
}
public String readString() {
- StringBuilder builder = new StringBuilder();
- while (mBuffers.size() > 0) {
- ByteBuffer bb = mBuffers.remove();
- builder.append(new String(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
- reclaim(bb);
- }
- remaining = 0;
- return builder.toString();
+ return readString(null);
+ }
+
+ public String readString(Charset charset) {
+ String ret = peekString(charset);
+ recycle();
+ return ret;
}
static class Reclaimer implements Comparator<ByteBuffer> {
@@ -387,7 +393,7 @@ public class ByteBufferList {
}
private static int MAX_SIZE = 1024 * 1024;
- private static int MAX_ITEM_SIZE = 1024 * 256;
+ public static int MAX_ITEM_SIZE = 1024 * 256;
static int currentSize = 0;
static int maxItem = 0;
@@ -503,4 +509,22 @@ public class ByteBufferList {
}
public static final ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
+
+ public static void writeOutputStream(OutputStream out, ByteBuffer b) throws IOException {
+ byte[] bytes;
+ int offset;
+ int length;
+ if (b.isDirect()) {
+ bytes = new byte[b.remaining()];
+ offset = 0;
+ length = b.remaining();
+ b.get(bytes);
+ }
+ else {
+ bytes = b.array();
+ offset = b.arrayOffset() + b.position();
+ length = b.remaining();
+ }
+ out.write(bytes, offset, length);
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/DataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/DataEmitter.java
index 2574901..cf8ac2a 100644
--- a/AndroidAsync/src/com/koushikdutta/async/DataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/DataEmitter.java
@@ -14,4 +14,5 @@ public interface DataEmitter {
public void setEndCallback(CompletedCallback callback);
public CompletedCallback getEndCallback();
public AsyncServer getServer();
+ public String charset();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java b/AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java
index 529ec8d..90e05c7 100644
--- a/AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java
+++ b/AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java
@@ -41,4 +41,9 @@ public abstract class DataEmitterBase implements DataEmitter {
public DataCallback getDataCallback() {
return mDataCallback;
}
+
+ @Override
+ public String charset() {
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
index 71bcfa9..10e8504 100644
--- a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
@@ -85,4 +85,11 @@ public class FilteredDataEmitter extends DataEmitterBase implements DataEmitter,
public void close() {
mEmitter.close();
}
+
+ @Override
+ public String charset() {
+ if (mEmitter == null)
+ return null;
+ return mEmitter.charset();
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/PushParser.java b/AndroidAsync/src/com/koushikdutta/async/PushParser.java
index c662f94..e02ac7f 100644
--- a/AndroidAsync/src/com/koushikdutta/async/PushParser.java
+++ b/AndroidAsync/src/com/koushikdutta/async/PushParser.java
@@ -360,7 +360,6 @@ public class PushParser implements DataCallback {
"}\n";
//null != "AndroidAsync: tap callback could not be found. Proguard? Use this in your proguard config:\n" + fail;
- assert false;
- return null;
+ throw new AssertionError(fail);
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java b/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java
index 42cd71a..6838590 100644
--- a/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java
+++ b/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java
@@ -15,7 +15,6 @@ public class ZipDataSink extends FilteredDataSink {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ZipOutputStream zop = new ZipOutputStream(bout);
- boolean first = true;
public void putNextEntry(ZipEntry ze) throws IOException {
zop.putNextEntry(ze);
@@ -31,7 +30,8 @@ public class ZipDataSink extends FilteredDataSink {
closed.onCompleted(e);
}
- public void close() {
+ @Override
+ public void end() {
try {
zop.close();
}
@@ -41,7 +41,7 @@ public class ZipDataSink extends FilteredDataSink {
}
setMaxBuffer(Integer.MAX_VALUE);
write(new ByteBufferList());
- super.close();
+ super.end();
}
@Override
@@ -50,7 +50,7 @@ public class ZipDataSink extends FilteredDataSink {
if (bb != null) {
while (bb.size() > 0) {
ByteBuffer b = bb.remove();
- zop.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
+ ByteBufferList.writeOutputStream(zop, b);
ByteBufferList.reclaim(b);
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/future/ConvertFuture.java b/AndroidAsync/src/com/koushikdutta/async/future/ConvertFuture.java
new file mode 100644
index 0000000..b07ac43
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/future/ConvertFuture.java
@@ -0,0 +1,13 @@
+package com.koushikdutta.async.future;
+
+/**
+ * Created by koush on 6/21/14.
+ */
+public abstract class ConvertFuture<T, F> extends TransformFuture<T, F> {
+ @Override
+ protected final void transform(F result) throws Exception {
+ setComplete(convert(result));
+ }
+
+ protected abstract Future<T> convert(F result) throws Exception;
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java b/AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java
index 81c1822..d03eaf9 100644
--- a/AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java
+++ b/AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java
@@ -1,31 +1,39 @@
package com.koushikdutta.async.future;
import android.os.Handler;
+import android.os.Looper;
/**
* Created by koush on 12/25/13.
*/
-public class HandlerFuture<T> extends TransformFuture<T, T> {
- Handler handler = new Handler();
+public class HandlerFuture<T> extends SimpleFuture<T> {
+ Handler handler;
- @Override
- protected void error(final Exception e) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- HandlerFuture.super.error(e);
- }
- });
+ public HandlerFuture() {
+ Looper looper = Looper.myLooper();
+ if (looper == null)
+ looper = Looper.getMainLooper();
+ handler = new Handler(looper);
}
@Override
- protected void transform(final T result) throws Exception {
- handler.post(new Runnable() {
+ public SimpleFuture<T> setCallback(final FutureCallback<T> callback) {
+ FutureCallback<T> wrapped = new FutureCallback<T>() {
@Override
- public void run() {
- if (!isCancelled())
- setComplete(result);
+ public void onCompleted(final Exception e, final T result) {
+ if (Looper.myLooper() == handler.getLooper()) {
+ callback.onCompleted(e, result);
+ return;
+ }
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ onCompleted(e, result);
+ }
+ });
}
- });
+ };
+ return super.setCallback(wrapped);
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/future/SimpleFuture.java b/AndroidAsync/src/com/koushikdutta/async/future/SimpleFuture.java
index dd33d54..11f5df3 100644
--- a/AndroidAsync/src/com/koushikdutta/async/future/SimpleFuture.java
+++ b/AndroidAsync/src/com/koushikdutta/async/future/SimpleFuture.java
@@ -14,6 +14,17 @@ public class SimpleFuture<T> extends SimpleCancellable implements DependentFutur
boolean silent;
FutureCallback<T> callback;
+ public SimpleFuture() {
+ }
+
+ public SimpleFuture(T value) {
+ setComplete(value);
+ }
+
+ public SimpleFuture(Exception e) {
+ setComplete(e);
+ }
+
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return cancel();
@@ -166,7 +177,7 @@ public class SimpleFuture<T> extends SimpleCancellable implements DependentFutur
}
@Override
- public <C extends FutureCallback<T>> C then(C callback) {
+ public final <C extends FutureCallback<T>> C then(C callback) {
if (callback instanceof DependentCancellable)
((DependentCancellable)callback).setParent(this);
setCallback(callback);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
index 7127d30..0034dbe 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
@@ -1,6 +1,8 @@
package com.koushikdutta.async.http;
+import android.annotation.SuppressLint;
import android.net.Uri;
+import android.os.Build;
import android.text.TextUtils;
import com.koushikdutta.async.AsyncSSLException;
@@ -36,9 +38,14 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.TimeoutException;
public class AsyncHttpClient {
@@ -67,6 +74,43 @@ public class AsyncHttpClient {
insertMiddleware(sslSocketMiddleware = new AsyncSSLSocketMiddleware(this));
}
+
+ @SuppressLint("NewApi")
+ private static void setupAndroidProxy(AsyncHttpRequest request) {
+ // using a explicit proxy?
+ if (request.proxyHost != null)
+ return;
+
+ List<Proxy> proxies;
+ try {
+ proxies = ProxySelector.getDefault().select(URI.create(request.getUri().toString()));
+ }
+ catch (Exception e) {
+ // uri parsing craps itself sometimes.
+ return;
+ }
+ if (proxies.isEmpty())
+ return;
+ Proxy proxy = proxies.get(0);
+ if (proxy.type() != Proxy.Type.HTTP)
+ return;
+ if (!(proxy.address() instanceof InetSocketAddress))
+ return;
+ InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
+ String proxyHost;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ proxyHost = proxyAddress.getHostString();
+ }
+ else {
+ InetAddress address = proxyAddress.getAddress();
+ if (address!=null)
+ proxyHost = address.getHostAddress();
+ else
+ proxyHost = proxyAddress.getHostName();
+ }
+ request.enableProxy(proxyHost, proxyAddress.getPort());
+ }
+
public AsyncSocketMiddleware getSocketMiddleware() {
return socketMiddleware;
}
@@ -260,15 +304,16 @@ public class AsyncHttpClient {
int responseCode = headers.getResponseCode();
if ((responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == 307) && request.getFollowRedirect()) {
String location = headers.get("Location");
- Uri redirect = Uri.parse(location);
- if (redirect == null || redirect.getScheme() == null) {
- try {
+ Uri redirect;
+ try {
+ redirect = Uri.parse(location);
+ if (redirect.getScheme() == null) {
redirect = Uri.parse(new URL(new URL(uri.toString()), location).toString());
}
- catch (Exception e) {
- reportConnectedCompleted(cancel, e, this, request, callback);
- return;
- }
+ }
+ catch (Exception e) {
+ reportConnectedCompleted(cancel, e, this, request, callback);
+ return;
}
final String method = request.getMethod().equals(AsyncHttpHead.METHOD) ? AsyncHttpHead.METHOD : AsyncHttpGet.METHOD;
AsyncHttpRequest newReq = new AsyncHttpRequest(redirect, method);
@@ -277,6 +322,7 @@ public class AsyncHttpClient {
newReq.LOGTAG = request.LOGTAG;
newReq.proxyHost = request.proxyHost;
newReq.proxyPort = request.proxyPort;
+ setupAndroidProxy(newReq);
copyHeader(request, newReq, "User-Agent");
copyHeader(request, newReq, "Range");
request.logi("Redirecting");
@@ -371,6 +417,9 @@ public class AsyncHttpClient {
}
};
+ // set up the system default proxy and connect
+ setupAndroidProxy(request);
+
synchronized (mMiddleware) {
for (AsyncHttpClientMiddleware middleware: mMiddleware) {
Cancellable socketCancellable = middleware.getSocket(data);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
index 2f2e4a8..135ec69 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
@@ -5,33 +5,11 @@ import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.future.Cancellable;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
+import com.koushikdutta.async.util.UntypedHashtable;
import java.util.Hashtable;
public interface AsyncHttpClientMiddleware {
- public static class UntypedHashtable {
- private Hashtable<String, Object> hash = new Hashtable<String, Object>();
-
- public void put(String key, Object value) {
- hash.put(key, value);
- }
-
- public void remove(String key) {
- hash.remove(key);
- }
-
- public <T> T get(String key, T defaultValue) {
- T ret = get(key);
- if (ret == null)
- return defaultValue;
- return ret;
- }
-
- public <T> T get(String key) {
- return (T)hash.get(key);
- }
- }
-
public static class GetSocketData {
public UntypedHashtable state = new UntypedHashtable();
public AsyncHttpRequest request;
@@ -50,11 +28,11 @@ public interface AsyncHttpClientMiddleware {
public static class OnBodyData extends OnHeadersReceivedData {
public DataEmitter bodyEmitter;
}
-
+
public static class OnRequestCompleteData extends OnBodyData {
public Exception exception;
}
-
+
public Cancellable getSocket(GetSocketData data);
public void onSocket(OnSocketData data);
public void onHeadersReceived(OnHeadersReceivedData data);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
index 35d9902..22316b5 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
@@ -16,7 +16,6 @@ import org.apache.http.RequestLine;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpParams;
-import java.net.URI;
import java.util.List;
import java.util.Map;
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
index 233c50b..70f10f7 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
@@ -1,5 +1,7 @@
package com.koushikdutta.async.http;
+import android.text.TextUtils;
+
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
@@ -15,8 +17,10 @@ import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
import com.koushikdutta.async.http.filter.ChunkedOutputFilter;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
+import com.koushikdutta.async.util.Charsets;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements AsyncHttpResponse {
private AsyncHttpRequestBody mWriter;
@@ -40,7 +44,7 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
if (mWriter != null) {
if (mRequest.getHeaders().getContentType() == null)
mRequest.getHeaders().setContentType(mWriter.getContentType());
- if (mWriter.length() > 0) {
+ if (mWriter.length() >= 0) {
mRequest.getHeaders().setContentLength(mWriter.length());
mSink = mSocket;
}
@@ -99,18 +103,19 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
}
}
};
-
+
protected abstract void onHeadersReceived();
-
+
StringCallback mHeaderCallback = new StringCallback() {
private RawHeaders mRawHeaders = new RawHeaders();
@Override
public void onStringAvailable(String s) {
try {
+ s = s.trim();
if (mRawHeaders.getStatusLine() == null) {
mRawHeaders.setStatusLine(s);
}
- else if (!"\r".equals(s)) {
+ else if (!TextUtils.isEmpty(s)) {
mRawHeaders.addLine(s);
}
else {
@@ -218,11 +223,6 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
}
@Override
- public void close() {
- mSink.close();
- }
-
- @Override
public void setClosedCallback(CompletedCallback handler) {
mSink.setClosedCallback(handler);
}
@@ -236,4 +236,14 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
public AsyncServer getServer() {
return mSocket.getServer();
}
+
+ @Override
+ public String charset() {
+ Multimap mm = Multimap.parseHeader(getHeaders().getHeaders(), "Content-Type");
+ String cs;
+ if (mm != null && null != (cs = mm.getString("charset")) && Charset.isSupported(cs)) {
+ return cs;
+ }
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLEngineConfigurator.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLEngineConfigurator.java
new file mode 100644
index 0000000..36af9c1
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLEngineConfigurator.java
@@ -0,0 +1,7 @@
+package com.koushikdutta.async.http;
+
+import javax.net.ssl.SSLEngine;
+
+public interface AsyncSSLEngineConfigurator {
+ public void configureEngine(SSLEngine engine, String host, int port);
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
index 7329911..82cc3ea 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
@@ -3,7 +3,7 @@ package com.koushikdutta.async.http;
import android.net.Uri;
import android.text.TextUtils;
-import com.koushikdutta.async.AsyncSSLException;
+import com.koushikdutta.async.AsyncSSLSocket;
import com.koushikdutta.async.AsyncSSLSocketWrapper;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.LineEmitter;
@@ -12,36 +12,79 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.http.libcore.RawHeaders;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
-import java.io.IOException;
-import java.net.URI;
-
public class AsyncSSLSocketMiddleware extends AsyncSocketMiddleware {
public AsyncSSLSocketMiddleware(AsyncHttpClient client) {
super(client, "https", 443);
}
- SSLContext sslContext;
+ protected SSLContext sslContext;
public void setSSLContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
- TrustManager[] trustManagers;
+ public SSLContext getSSLContext() {
+ return sslContext != null ? sslContext : AsyncSSLSocketWrapper.getDefaultSSLContext();
+ }
+
+ protected TrustManager[] trustManagers;
public void setTrustManagers(TrustManager[] trustManagers) {
this.trustManagers = trustManagers;
}
- HostnameVerifier hostnameVerifier;
+ protected HostnameVerifier hostnameVerifier;
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}
+ protected List<AsyncSSLEngineConfigurator> engineConfigurators = new ArrayList<AsyncSSLEngineConfigurator>();
+
+ public void addEngineConfigurator(AsyncSSLEngineConfigurator engineConfigurator) {
+ engineConfigurators.add(engineConfigurator);
+ }
+
+ public void clearEngineConfigurators() {
+ engineConfigurators.clear();
+ }
+
+ protected SSLEngine createConfiguredSSLEngine(String host, int port) {
+ SSLContext sslContext = getSSLContext();
+ SSLEngine sslEngine = sslContext.createSSLEngine();
+
+ for (AsyncSSLEngineConfigurator configurator : engineConfigurators) {
+ configurator.configureEngine(sslEngine, host, port);
+ }
+
+ return sslEngine;
+ }
+
+ protected AsyncSSLSocketWrapper.HandshakeCallback createHandshakeCallback(final ConnectCallback callback) {
+ return new AsyncSSLSocketWrapper.HandshakeCallback() {
+ @Override
+ public void onHandshakeCompleted(Exception e, AsyncSSLSocket socket) {
+ callback.onConnectCompleted(e, socket);
+ }
+ };
+ }
+
+ protected void tryHandshake(final ConnectCallback callback, AsyncSocket socket, final Uri uri, final int port) {
+ AsyncSSLSocketWrapper.handshake(socket, uri.getHost(), port,
+ createConfiguredSSLEngine(uri.getHost(), port),
+ trustManagers, hostnameVerifier, true,
+ createHandshakeCallback(callback));
+ }
+
@Override
protected ConnectCallback wrapCallback(final ConnectCallback callback, final Uri uri, final int port, final boolean proxied) {
return new ConnectCallback() {
@@ -49,7 +92,7 @@ public class AsyncSSLSocketMiddleware extends AsyncSocketMiddleware {
public void onConnectCompleted(Exception ex, final AsyncSocket socket) {
if (ex == null) {
if (!proxied) {
- callback.onConnectCompleted(null, new AsyncSSLSocketWrapper(socket, uri.getHost(), port, sslContext, trustManagers, hostnameVerifier, true));
+ tryHandshake(callback, socket, uri, port);
}
else {
// this SSL connection is proxied, must issue a CONNECT request to the proxy server
@@ -81,7 +124,7 @@ public class AsyncSSLSocketMiddleware extends AsyncSocketMiddleware {
socket.setDataCallback(null);
socket.setEndCallback(null);
if (TextUtils.isEmpty(s.trim())) {
- callback.onConnectCompleted(null, new AsyncSSLSocketWrapper(socket, uri.getHost(), port, sslContext, trustManagers, hostnameVerifier, true));
+ tryHandshake(callback, socket, uri, port);
}
else {
callback.onConnectCompleted(new IOException("unknown second status line"), socket);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
index 8e8a36e..e293d23 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
@@ -50,7 +50,7 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
this(client, "http", 80);
}
- AsyncHttpClient mClient;
+ protected AsyncHttpClient mClient;
protected ConnectCallback wrapCallback(ConnectCallback callback, Uri uri, int port, boolean proxied) {
return callback;
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java b/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
index dba79c0..9b08241 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
@@ -35,7 +35,7 @@ public class HttpUtil {
return new StringBody();
}
if (MultipartFormDataBody.CONTENT_TYPE.equals(ct)) {
- return new MultipartFormDataBody(contentType, values);
+ return new MultipartFormDataBody(values);
}
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java b/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
index dd8e82c..e1b4015 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java
@@ -302,6 +302,10 @@ abstract class HybiParser {
return frame(OP_BINARY, data, -1, offset, length);
}
+ public byte[] pingFrame(String data) {
+ return frame(OP_PING, data, -1);
+ }
+
/**
* Flip the opcode so to avoid the name collision with the public method
*
@@ -378,10 +382,6 @@ abstract class HybiParser {
return frame;
}
- public void ping(String message) {
-// send(frame(message, OP_PING, -1));
- }
-
public void close(int code, String reason) {
if (mClosed) return;
sendFrame(frame(OP_CLOSE, reason, code));
@@ -432,7 +432,7 @@ abstract class HybiParser {
}
} else if (opcode == OP_CLOSE) {
- int code = (payload.length >= 2) ? 256 * payload[0] + payload[1] : 0;
+ int code = (payload.length >= 2) ? 256 * (payload[0] & 0xFF) + (payload[1] & 0xFF) : 0;
String reason = (payload.length > 2) ? encode(slice(payload, 2)) : null;
// Log.d(TAG, "Got close op! " + code + " " + reason);
onDisconnect(code, reason);
@@ -444,13 +444,14 @@ abstract class HybiParser {
} else if (opcode == OP_PONG) {
String message = encode(payload);
- // FIXME: Fire callback...
+ onPong(message);
// Log.d(TAG, "Got pong! " + message);
}
}
protected abstract void onMessage(byte[] payload);
protected abstract void onMessage(String payload);
+ protected abstract void onPong(String payload);
protected abstract void onDisconnect(int code, String reason);
protected abstract void report(Exception ex);
@@ -509,4 +510,4 @@ abstract class HybiParser {
return value;
}
-} \ No newline at end of file
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/Multimap.java b/AndroidAsync/src/com/koushikdutta/async/http/Multimap.java
index 24dfc5a..628bdd0 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/Multimap.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/Multimap.java
@@ -50,6 +50,8 @@ public class Multimap extends Hashtable<String, List<String>> implements Iterabl
}
public static Multimap parseHeader(String header) {
+ if (header == null)
+ return null;
Multimap map = new Multimap();
String[] parts = header.split(";");
for (String part: parts) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
index cfa693f..3715fb7 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
@@ -8,24 +8,23 @@ import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataEmitter;
-import com.koushikdutta.async.DataEmitterBase;
import com.koushikdutta.async.FilteredDataEmitter;
import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.koushikdutta.async.future.Cancellable;
import com.koushikdutta.async.future.SimpleCancellable;
-import com.koushikdutta.async.http.libcore.Charsets;
+import com.koushikdutta.async.util.Charsets;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
import com.koushikdutta.async.http.libcore.ResponseSource;
import com.koushikdutta.async.http.libcore.StrictLineReader;
+import com.koushikdutta.async.util.Allocator;
import com.koushikdutta.async.util.FileCache;
import com.koushikdutta.async.util.StreamUtility;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -35,7 +34,6 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.CacheResponse;
-import java.net.URI;
import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -45,6 +43,8 @@ import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
+import javax.net.ssl.SSLEngine;
+
public class ResponseCacheMiddleware extends SimpleMiddleware {
public static final int ENTRY_METADATA = 0;
public static final int ENTRY_BODY = 1;
@@ -147,6 +147,9 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
ResponseHeaders cachedResponseHeaders = new ResponseHeaders(data.request.getUri(), rawResponseHeaders);
+ rawResponseHeaders.set("Content-Length", String.valueOf(contentLength));
+ rawResponseHeaders.removeAll("Content-Encoding");
+ rawResponseHeaders.removeAll("Transfer-Encoding");
cachedResponseHeaders.setLocalTimestamps(System.currentTimeMillis(), System.currentTimeMillis());
long now = System.currentTimeMillis();
@@ -155,9 +158,6 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
if (responseSource == ResponseSource.CACHE) {
data.request.logi("Response retrieved from cache");
final CachedSocket socket = entry.isHttps() ? new CachedSSLSocket(candidate, contentLength) : new CachedSocket(candidate, contentLength);
- rawResponseHeaders.removeAll("Content-Encoding");
- rawResponseHeaders.removeAll("Transfer-Encoding");
- rawResponseHeaders.set("Content-Length", String.valueOf(contentLength));
socket.pending.add(ByteBuffer.wrap(rawResponseHeaders.toHeaderString().getBytes()));
server.post(new Runnable() {
@@ -219,14 +219,14 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
if (cacheData != null) {
if (cacheData.cachedResponseHeaders.validate(data.headers)) {
data.request.logi("Serving response from conditional cache");
+ data.headers.getHeaders().removeAll("Content-Length");
data.headers = cacheData.cachedResponseHeaders.combine(data.headers);
data.headers.getHeaders().setStatusLine(cacheData.cachedResponseHeaders.getHeaders().getStatusLine());
data.headers.getHeaders().set(SERVED_FROM, CONDITIONAL_CACHE);
conditionalCacheHitCount++;
- BodySpewer bodySpewer = new BodySpewer(cacheData.contentLength);
- bodySpewer.cacheResponse = cacheData.candidate;
+ CachedBodyEmitter bodySpewer = new CachedBodyEmitter(cacheData.candidate, cacheData.contentLength);
bodySpewer.setDataEmitter(data.bodyEmitter);
data.bodyEmitter = bodySpewer;
bodySpewer.spew();
@@ -341,7 +341,7 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
while (!bb.isEmpty()) {
ByteBuffer b = bb.remove();
try {
- outputStream.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
+ ByteBufferList.writeOutputStream(outputStream, b);
}
finally {
copy.add(b);
@@ -384,54 +384,62 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
}
}
- private static class BodySpewer extends FilteredDataEmitter {
- long contentLength;
+ private static class CachedBodyEmitter extends FilteredDataEmitter {
EntryCacheResponse cacheResponse;
- boolean first = true;
ByteBufferList pending = new ByteBufferList();
- boolean paused;
+ private boolean paused;
+ private Allocator allocator = new Allocator();
boolean allowEnd;
- public BodySpewer(long contentLength) {
- this.contentLength = contentLength;
+ public CachedBodyEmitter(EntryCacheResponse cacheResponse, long contentLength) {
+ this.cacheResponse = cacheResponse;
+ allocator.setCurrentAlloc((int)contentLength);
}
+ Runnable spewRunnable = new Runnable() {
+ @Override
+ public void run() {
+ spewInternal();
+ }
+ };
+
void spewInternal() {
if (pending.remaining() > 0) {
- com.koushikdutta.async.Util.emitAllData(BodySpewer.this, pending);
+ com.koushikdutta.async.Util.emitAllData(CachedBodyEmitter.this, pending);
if (pending.remaining() > 0)
return;
}
// fill pending
try {
- assert first;
- if (!first)
- return;
- first = false;
- ByteBuffer buffer = ByteBufferList.obtain((int)contentLength);
+ ByteBuffer buffer = allocator.allocate();
assert buffer.position() == 0;
- DataInputStream din = new DataInputStream(cacheResponse.getBody());
- din.readFully(buffer.array(), buffer.arrayOffset(), (int)contentLength);
- buffer.limit((int)contentLength);
+ FileInputStream din = cacheResponse.getBody();
+ int read = din.read(buffer.array(), buffer.arrayOffset(), buffer.capacity());
+ if (read == -1) {
+ ByteBufferList.reclaim(buffer);
+ allowEnd = true;
+ report(null);
+ return;
+ }
+ allocator.track(read);
+ buffer.limit(read);
pending.add(buffer);
- com.koushikdutta.async.Util.emitAllData(this, pending);
- assert din.read() == -1;
- allowEnd = true;
- report(null);
}
catch (IOException e) {
allowEnd = true;
report(e);
+ return;
}
+ com.koushikdutta.async.Util.emitAllData(this, pending);
+ if (pending.remaining() > 0)
+ return;
+ // this limits max throughput to 256k (aka max alloc) * 100 per second...
+ // roughly 25MB/s
+ getServer().postDelayed(spewRunnable, 10);
}
void spew() {
- getServer().post(new Runnable() {
- @Override
- public void run() {
- spewInternal();
- }
- });
+ getServer().post(spewRunnable);
}
@Override
@@ -447,6 +455,8 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
@Override
protected void report(Exception e) {
+ // a 304 response will immediate call report/end since there is no body.
+ // prevent this from happening by waiting for the actual body to be spit out.
if (!allowEnd)
return;
StreamUtility.closeQuietly(cacheResponse.getBody());
@@ -671,23 +681,23 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
}
@Override
+ public SSLEngine getSSLEngine() {
+ return null;
+ }
+
+ @Override
public X509Certificate[] getPeerCertificates() {
return null;
}
}
- private class CachedSocket extends DataEmitterBase implements AsyncSocket {
- EntryCacheResponse cacheResponse;
- long contentLength;
- boolean paused;
+ private class CachedSocket extends CachedBodyEmitter implements AsyncSocket {
boolean closed;
- boolean first = true;
- ByteBufferList pending = new ByteBufferList();
boolean open;
CompletedCallback closedCallback;
public CachedSocket(EntryCacheResponse cacheResponse, long contentLength) {
- this.cacheResponse = cacheResponse;
- this.contentLength = contentLength;
+ super(cacheResponse, contentLength);
+ allowEnd = true;
}
@Override
@@ -695,19 +705,8 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
}
@Override
- public boolean isChunked() {
- return false;
- }
-
- @Override
- public void pause() {
- paused = true;
- }
-
- @Override
protected void report(Exception e) {
super.report(e);
- StreamUtility.closeQuietly(cacheResponse.getBody());
if (closed)
return;
closed = true;
@@ -715,54 +714,6 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
closedCallback.onCompleted(e);
}
- void spewInternal() {
- if (pending.remaining() > 0) {
- com.koushikdutta.async.Util.emitAllData(CachedSocket.this, pending);
- if (pending.remaining() > 0)
- return;
- }
-
- // fill pending
- try {
- assert first;
- if (!first)
- return;
- first = false;
- ByteBuffer buffer = ByteBufferList.obtain((int)contentLength);
- assert buffer.position() == 0;
- DataInputStream din = new DataInputStream(cacheResponse.getBody());
- din.readFully(buffer.array(), buffer.arrayOffset(), (int)contentLength);
- buffer.limit((int)contentLength);
- pending.add(buffer);
- com.koushikdutta.async.Util.emitAllData(CachedSocket.this, pending);
- assert din.read() == -1;
- report(null);
- }
- catch (IOException e) {
- report(e);
- }
- }
-
- void spew() {
- getServer().post(new Runnable() {
- @Override
- public void run() {
- spewInternal();
- }
- });
- }
-
- @Override
- public void resume() {
- paused = false;
- spew();
- }
-
- @Override
- public boolean isPaused() {
- return paused;
- }
-
@Override
public void write(ByteBuffer bb) {
// it's gonna write headers and stuff... whatever
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java b/AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java
index 8242381..1aaafa6 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java
@@ -7,14 +7,21 @@ public interface WebSocket extends AsyncSocket {
static public interface StringCallback {
public void onStringAvailable(String s);
}
+ static public interface PongCallback {
+ public void onPongReceived(String s);
+ }
public void send(byte[] bytes);
public void send(String string);
public void send(byte [] bytes, int offset, int len);
+ public void ping(String message);
public void setStringCallback(StringCallback callback);
public StringCallback getStringCallback();
-
+
+ public void setPongCallback(PongCallback callback);
+ public PongCallback getPongCallback();
+
public boolean isBuffering();
public AsyncSocket getSocket();
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
index 96e724a..e4a2787 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/WebSocketImpl.java
@@ -98,6 +98,12 @@ public class WebSocketImpl implements WebSocket {
protected void sendFrame(byte[] frame) {
mSink.write(ByteBuffer.wrap(frame));
}
+
+ @Override
+ protected void onPong(String payload) {
+ if (WebSocketImpl.this.mPongCallback != null)
+ WebSocketImpl.this.mPongCallback.onPongReceived(payload);
+ }
};
mParser.setMasking(masking);
mParser.setDeflate(deflate);
@@ -228,6 +234,11 @@ public class WebSocketImpl implements WebSocket {
mSink.write(ByteBuffer.wrap(mParser.frame(string)));
}
+ @Override
+ public void ping(String string) {
+ mSink.write(ByteBuffer.wrap(mParser.pingFrame(string)));
+ }
+
private StringCallback mStringCallback;
@Override
public void setStringCallback(StringCallback callback) {
@@ -245,6 +256,17 @@ public class WebSocketImpl implements WebSocket {
return mStringCallback;
}
+ private PongCallback mPongCallback;
+ @Override
+ public void setPongCallback(PongCallback callback) {
+ mPongCallback = callback;
+ }
+
+ @Override
+ public PongCallback getPongCallback() {
+ return mPongCallback;
+ }
+
@Override
public DataCallback getDataCallback() {
return mDataCallback;
@@ -314,4 +336,9 @@ public class WebSocketImpl implements WebSocket {
public boolean isPaused() {
return mSocket.isPaused();
}
+
+ @Override
+ public String charset() {
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/body/MultipartFormDataBody.java b/AndroidAsync/src/com/koushikdutta/async/http/body/MultipartFormDataBody.java
index 8fdd378..c61a9d9 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/body/MultipartFormDataBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/body/MultipartFormDataBody.java
@@ -100,7 +100,8 @@ public class MultipartFormDataBody extends BoundaryEmitter implements AsyncHttpR
}
public static final String CONTENT_TYPE = "multipart/form-data";
- public MultipartFormDataBody(String contentType, String[] values) {
+ String contentType = CONTENT_TYPE;
+ public MultipartFormDataBody(String[] values) {
for (String value: values) {
String[] splits = value.split("=");
if (splits.length != 2)
@@ -154,7 +155,9 @@ public class MultipartFormDataBody extends BoundaryEmitter implements AsyncHttpR
.add(new ContinuationCallback() {
@Override
public void onContinue(Continuation continuation, CompletedCallback next) throws Exception {
- written += part.length();
+ long partLength = part.length();
+ if (partLength >= 0)
+ written += partLength;
part.write(sink, next);
}
})
@@ -213,7 +216,11 @@ public class MultipartFormDataBody extends BoundaryEmitter implements AsyncHttpR
public MultipartFormDataBody() {
}
-
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
public void addFilePart(String name, File file) {
addPart(new FilePart(name, file));
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/body/Part.java b/AndroidAsync/src/com/koushikdutta/async/http/body/Part.java
index aacf5c2..cfe4993 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/body/Part.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/body/Part.java
@@ -24,8 +24,8 @@ public class Part {
return mContentDisposition.getString("name");
}
- private int length = -1;
- public Part(String name, int length, List<NameValuePair> contentDisposition) {
+ private long length = -1;
+ public Part(String name, long length, List<NameValuePair> contentDisposition) {
this.length = length;
mHeaders = new RawHeaders();
StringBuilder builder = new StringBuilder(String.format("form-data; name=\"%s\"", name));
@@ -61,7 +61,7 @@ public class Part {
return mContentDisposition.containsKey("filename");
}
- public int length() {
+ public long length() {
return length;
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java b/AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java
index 0a3bb0f..d48704b 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java
@@ -10,7 +10,7 @@ import com.koushikdutta.async.DataSink;
import com.koushikdutta.async.callback.CompletedCallback;
public abstract class StreamPart extends Part {
- public StreamPart(String name, int length, List<NameValuePair> contentDisposition) {
+ public StreamPart(String name, long length, List<NameValuePair> contentDisposition) {
super(name, length, contentDisposition);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/body/UrlEncodedFormBody.java b/AndroidAsync/src/com/koushikdutta/async/http/body/UrlEncodedFormBody.java
index b50b7c7..7bceceb 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/body/UrlEncodedFormBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/body/UrlEncodedFormBody.java
@@ -8,6 +8,7 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.http.AsyncHttpRequest;
import com.koushikdutta.async.http.Multimap;
+import com.koushikdutta.async.util.Charsets;
import org.apache.http.NameValuePair;
@@ -42,7 +43,7 @@ public class UrlEncodedFormBody implements AsyncHttpRequestBody<Multimap> {
b.append('=');
b.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
}
- mBodyBytes = b.toString().getBytes("ISO-8859-1");
+ mBodyBytes = b.toString().getBytes("UTF-8");
}
catch (UnsupportedEncodingException e) {
}
@@ -58,7 +59,7 @@ public class UrlEncodedFormBody implements AsyncHttpRequestBody<Multimap> {
public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
@Override
public String getContentType() {
- return CONTENT_TYPE;
+ return CONTENT_TYPE + "; charset=utf8";
}
@Override
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/filter/GZIPInputFilter.java b/AndroidAsync/src/com/koushikdutta/async/http/filter/GZIPInputFilter.java
index e1a23d0..04eb9c9 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/filter/GZIPInputFilter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/filter/GZIPInputFilter.java
@@ -89,14 +89,23 @@ public class GZIPInputFilter extends InflaterInputFilter {
ByteBufferList.reclaim(b);
}
}
+ bb.recycle();
+ done();
}
};
if ((flags & FNAME) != 0) {
parser.until((byte) 0, summer);
+ return;
}
if ((flags & FCOMMENT) != 0) {
parser.until((byte) 0, summer);
+ return;
}
+
+ done();
+ }
+
+ private void done() {
if (hcrc) {
parser.readByteArray(2, new ParseCallback<byte[]>() {
public void parsed(byte[] header) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java b/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
index e96f284..3ae1363 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
@@ -14,6 +14,7 @@ public class InflaterInputFilter extends FilteredDataEmitter {
@Override
protected void report(Exception e) {
+ mInflater.end();
if (e != null && mInflater.getRemaining() > 0) {
e = new DataRemainingException("data still remaining in inflater", e);
}
@@ -35,8 +36,7 @@ public class InflaterInputFilter extends FilteredDataEmitter {
int inflated = mInflater.inflate(output.array(), output.arrayOffset() + output.position(), output.remaining());
output.position(output.position() + inflated);
if (!output.hasRemaining()) {
- output.limit(output.position());
- output.position(0);
+ output.flip();
transformed.add(output);
assert totalRead != 0;
int newSize = output.capacity() * 2;
@@ -47,8 +47,7 @@ public class InflaterInputFilter extends FilteredDataEmitter {
}
ByteBufferList.reclaim(b);
}
- output.limit(output.position());
- output.position(0);
+ output.flip();
transformed.add(output);
Util.emitAllData(this, transformed);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/libcore/RequestHeaders.java b/AndroidAsync/src/com/koushikdutta/async/http/libcore/RequestHeaders.java
index 3216bd5..b5180b4 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/libcore/RequestHeaders.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/libcore/RequestHeaders.java
@@ -212,7 +212,9 @@ public final class RequestHeaders {
if (this.contentLength != -1) {
headers.removeAll("Content-Length");
}
- headers.add("Content-Length", Integer.toString(contentLength));
+ if (contentLength != -1) {
+ headers.add("Content-Length", Integer.toString(contentLength));
+ }
this.contentLength = contentLength;
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/libcore/StrictLineReader.java b/AndroidAsync/src/com/koushikdutta/async/http/libcore/StrictLineReader.java
index 6c6308f..d1cb5d9 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/libcore/StrictLineReader.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/libcore/StrictLineReader.java
@@ -16,6 +16,8 @@
package com.koushikdutta.async.http.libcore;
+import com.koushikdutta.async.util.Charsets;
+
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
index 331c1be..4259d1d 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
@@ -1,9 +1,12 @@
package com.koushikdutta.async.http.server;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.AssetManager;
+import android.os.Build;
import android.text.TextUtils;
+import com.koushikdutta.async.AsyncSSLSocket;
import com.koushikdutta.async.AsyncSSLSocketWrapper;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncServerSocket;
@@ -39,6 +42,7 @@ import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
+@TargetApi(Build.VERSION_CODES.ECLAIR)
public class AsyncHttpServer {
ArrayList<AsyncServerSocket> mListeners = new ArrayList<AsyncServerSocket>();
public void stop() {
@@ -223,8 +227,14 @@ public class AsyncHttpServer {
AsyncServer.getDefault().listen(null, port, new ListenCallback() {
@Override
public void onAccepted(AsyncSocket socket) {
- AsyncSSLSocketWrapper sslSocket = new AsyncSSLSocketWrapper(socket, null, port, sslContext, null, null, false);
- mListenCallback.onAccepted(sslSocket);
+ AsyncSSLSocketWrapper.handshake(socket, null, port, sslContext.createSSLEngine(), null, null, false,
+ new AsyncSSLSocketWrapper.HandshakeCallback() {
+ @Override
+ public void onHandshakeCompleted(Exception e, AsyncSSLSocket socket) {
+ if (socket != null)
+ mListenCallback.onAccepted(socket);
+ }
+ });
}
@Override
@@ -308,11 +318,15 @@ public class AsyncHttpServer {
response.end();
return;
}
- callback.onConnected(new WebSocketImpl(request, response), request.getHeaders());
+ callback.onConnected(createWebSocket(request, response), request.getHeaders());
}
});
}
+ protected WebSocket createWebSocket(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
+ return new WebSocketImpl(request, response);
+ }
+
public void get(String regex, HttpServerRequestCallback callback) {
addAction(AsyncHttpGet.METHOD, regex, callback);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
index 4689bec..bd7211b 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
@@ -318,11 +318,7 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
@Override
public void close() {
- end();
- if (mSink != null)
- mSink.close();
- else
- mSocket.close();
+ mSocket.close();
}
@Override
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/socketio/SocketIOClient.java b/AndroidAsync/src/com/koushikdutta/async/http/socketio/SocketIOClient.java
index 344aab8..af469b6 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/socketio/SocketIOClient.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/socketio/SocketIOClient.java
@@ -1,9 +1,7 @@
package com.koushikdutta.async.http.socketio;
-import android.os.Handler;
import android.text.TextUtils;
-import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.SimpleFuture;
import com.koushikdutta.async.http.AsyncHttpClient;
@@ -12,6 +10,7 @@ import com.koushikdutta.async.http.socketio.transport.SocketIOTransport;
import org.json.JSONArray;
import org.json.JSONObject;
+@Deprecated
public class SocketIOClient extends EventEmitter {
boolean connected;
boolean disconnected;
diff --git a/AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java b/AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java
index 7886662..89a611c 100644
--- a/AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java
+++ b/AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java
@@ -7,17 +7,20 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.TransformFuture;
+import java.nio.charset.Charset;
+
/**
* Created by koush on 5/27/13.
*/
public class StringParser implements AsyncParser<String> {
@Override
public Future<String> parse(DataEmitter emitter) {
+ final String charset = emitter.charset();
return new ByteBufferListParser().parse(emitter)
.then(new TransformFuture<String, ByteBufferList>() {
@Override
protected void transform(ByteBufferList result) throws Exception {
- setComplete(result.readString());
+ setComplete(result.readString(charset != null ? Charset.forName(charset) : null));
}
});
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/stream/InputStreamDataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/stream/InputStreamDataEmitter.java
index bdf7993..c63891c 100644
--- a/AndroidAsync/src/com/koushikdutta/async/stream/InputStreamDataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/stream/InputStreamDataEmitter.java
@@ -146,4 +146,9 @@ public class InputStreamDataEmitter implements DataEmitter {
catch (Exception e) {
}
}
+
+ @Override
+ public String charset() {
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java b/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java
index d4def38..13bb419 100644
--- a/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java
+++ b/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java
@@ -17,7 +17,19 @@ public class OutputStreamDataSink implements DataSink {
@Override
public void end() {
- close();
+ try {
+ if (mStream != null)
+ mStream.close();
+ reportClose(null);
+ }
+ catch (IOException e) {
+ reportClose(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ end();
}
AsyncServer server;
@@ -35,31 +47,6 @@ public class OutputStreamDataSink implements DataSink {
return mStream;
}
- private boolean doPending() {
- try {
- while (pending.size() > 0) {
- ByteBuffer b;
- synchronized (pending) {
- b = pending.remove();
- }
- int rem = b.remaining();
- getOutputStream().write(b.array(), b.arrayOffset() + b.position(), b.remaining());
- totalWritten += rem;
- ByteBufferList.reclaim(b);
- }
- return true;
- }
- catch (Exception e) {
- pending.recycle();
- closeReported = true;
- closeException = e;
- return false;
- }
- }
-
- final ByteBufferList pending = new ByteBufferList();
- int totalWritten;
-
@Override
public void write(final ByteBuffer bb) {
try {
@@ -104,18 +91,6 @@ public class OutputStreamDataSink implements DataSink {
public boolean isOpen() {
return closeReported;
}
-
- @Override
- public void close() {
- try {
- if (mStream != null)
- mStream.close();
- reportClose(null);
- }
- catch (IOException e) {
- reportClose(e);
- }
- }
boolean closeReported;
Exception closeException;
diff --git a/AndroidAsync/src/com/koushikdutta/async/util/Allocator.java b/AndroidAsync/src/com/koushikdutta/async/util/Allocator.java
new file mode 100644
index 0000000..608026d
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/util/Allocator.java
@@ -0,0 +1,48 @@
+package com.koushikdutta.async.util;
+
+import com.koushikdutta.async.ByteBufferList;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Created by koush on 6/28/14.
+ */
+public class Allocator {
+ final int maxAlloc;
+ int currentAlloc = 0;
+ int minAlloc = 2 << 11;
+
+ public Allocator(int maxAlloc) {
+ this.maxAlloc = maxAlloc;
+ }
+
+ public Allocator() {
+ maxAlloc = ByteBufferList.MAX_ITEM_SIZE;
+ }
+
+ public ByteBuffer allocate() {
+ return ByteBufferList.obtain(Math.min(Math.max(currentAlloc, minAlloc), maxAlloc));
+ }
+
+ public void track(long read) {
+ currentAlloc = (int)read * 2;
+ }
+
+ public int getMaxAlloc() {
+ return maxAlloc;
+ }
+
+ public void setCurrentAlloc(int currentAlloc) {
+ this.currentAlloc = currentAlloc;
+ }
+
+ public int getMinAlloc() {
+ return minAlloc;
+ }
+
+ public Allocator setMinAlloc(int minAlloc ) {
+ this.minAlloc = minAlloc;
+ return this;
+ }
+}
+
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/libcore/Charsets.java b/AndroidAsync/src/com/koushikdutta/async/util/Charsets.java
index 575b147..c3a1e44 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/libcore/Charsets.java
+++ b/AndroidAsync/src/com/koushikdutta/async/util/Charsets.java
@@ -1,4 +1,4 @@
-package com.koushikdutta.async.http.libcore;
+package com.koushikdutta.async.util;
import java.nio.charset.Charset;
diff --git a/AndroidAsync/src/com/koushikdutta/async/util/FileCache.java b/AndroidAsync/src/com/koushikdutta/async/util/FileCache.java
index 3ce4b97..d117108 100644
--- a/AndroidAsync/src/com/koushikdutta/async/util/FileCache.java
+++ b/AndroidAsync/src/com/koushikdutta/async/util/FileCache.java
@@ -6,6 +6,8 @@ import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -41,17 +43,42 @@ public class FileCache {
}
}
+ private static String hashAlgorithm = "MD5";
+
+ private static MessageDigest findAlternativeMessageDigest() {
+ if ("MD5".equals(hashAlgorithm)) {
+ for (Provider provider : Security.getProviders()) {
+ for (Provider.Service service : provider.getServices()) {
+ hashAlgorithm = service.getAlgorithm();
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm);
+ if (messageDigest != null)
+ return messageDigest;
+ } catch (NoSuchAlgorithmException ignored) {
+ }
+ }
+ }
+ }
+ return null;
+ }
+
public static String toKeyString(Object... parts) {
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("MD5");
- for (Object part: parts) {
- messageDigest.update(part.toString().getBytes());
+ MessageDigest messageDigest;
+ synchronized (FileCache.class) {
+ try {
+ messageDigest = MessageDigest.getInstance(hashAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ messageDigest = findAlternativeMessageDigest();
+ if (null == messageDigest)
+ throw new RuntimeException(e);
}
- byte[] md5bytes = messageDigest.digest();
- return new BigInteger(1, md5bytes).toString(16);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
}
+
+ for (Object part : parts) {
+ messageDigest.update(part.toString().getBytes());
+ }
+ byte[] md5bytes = messageDigest.digest();
+ return new BigInteger(1, md5bytes).toString(16);
}
boolean loadAsync;
diff --git a/AndroidAsync/src/com/koushikdutta/async/util/StreamUtility.java b/AndroidAsync/src/com/koushikdutta/async/util/StreamUtility.java
index 95911dd..4d55e2f 100644
--- a/AndroidAsync/src/com/koushikdutta/async/util/StreamUtility.java
+++ b/AndroidAsync/src/com/koushikdutta/async/util/StreamUtility.java
@@ -102,5 +102,10 @@ public class StreamUtility {
}
}
}
+
+ public static void eat(InputStream input) throws IOException {
+ byte[] stuff = new byte[1024];
+ while (input.read(stuff) != -1);
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/util/UntypedHashtable.java b/AndroidAsync/src/com/koushikdutta/async/util/UntypedHashtable.java
new file mode 100644
index 0000000..a159d97
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/util/UntypedHashtable.java
@@ -0,0 +1,26 @@
+package com.koushikdutta.async.util;
+
+import java.util.Hashtable;
+
+public class UntypedHashtable {
+ private Hashtable<String, Object> hash = new Hashtable<String, Object>();
+
+ public void put(String key, Object value) {
+ hash.put(key, value);
+ }
+
+ public void remove(String key) {
+ hash.remove(key);
+ }
+
+ public <T> T get(String key, T defaultValue) {
+ T ret = get(key);
+ if (ret == null)
+ return defaultValue;
+ return ret;
+ }
+
+ public <T> T get(String key) {
+ return (T)hash.get(key);
+ }
+} \ No newline at end of file
diff --git a/AndroidAsyncTest/testdata/6691924d7d24237d3b3679310157d640 b/AndroidAsync/test/assets/6691924d7d24237d3b3679310157d640
index cdd924a..cdd924a 100644
--- a/AndroidAsyncTest/testdata/6691924d7d24237d3b3679310157d640
+++ b/AndroidAsync/test/assets/6691924d7d24237d3b3679310157d640
Binary files differ
diff --git a/AndroidAsyncTest/testdata/hello.txt b/AndroidAsync/test/assets/hello.txt
index 95d09f2..95d09f2 100644
--- a/AndroidAsyncTest/testdata/hello.txt
+++ b/AndroidAsync/test/assets/hello.txt
diff --git a/AndroidAsyncTest/testdata/test.json b/AndroidAsync/test/assets/test.json
index b42f309..b42f309 100644
--- a/AndroidAsyncTest/testdata/test.json
+++ b/AndroidAsync/test/assets/test.json
diff --git a/AndroidAsyncTest/res/drawable-hdpi/ic_launcher.png b/AndroidAsync/test/res/drawable-hdpi/ic_launcher.png
index 96a442e..96a442e 100644
--- a/AndroidAsyncTest/res/drawable-hdpi/ic_launcher.png
+++ b/AndroidAsync/test/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidAsyncTest/res/drawable-ldpi/ic_launcher.png b/AndroidAsync/test/res/drawable-ldpi/ic_launcher.png
index 9923872..9923872 100644
--- a/AndroidAsyncTest/res/drawable-ldpi/ic_launcher.png
+++ b/AndroidAsync/test/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/AndroidAsyncTest/res/drawable-mdpi/ic_launcher.png b/AndroidAsync/test/res/drawable-mdpi/ic_launcher.png
index 359047d..359047d 100644
--- a/AndroidAsyncTest/res/drawable-mdpi/ic_launcher.png
+++ b/AndroidAsync/test/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidAsyncTest/res/drawable-xhdpi/ic_launcher.png b/AndroidAsync/test/res/drawable-xhdpi/ic_launcher.png
index 71c6d76..71c6d76 100644
--- a/AndroidAsyncTest/res/drawable-xhdpi/ic_launcher.png
+++ b/AndroidAsync/test/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidAsyncTest/res/raw/keystore.bks b/AndroidAsync/test/res/raw/keystore.bks
index acf703c..acf703c 100644
--- a/AndroidAsyncTest/res/raw/keystore.bks
+++ b/AndroidAsync/test/res/raw/keystore.bks
Binary files differ
diff --git a/AndroidAsyncTest/res/values/strings.xml b/AndroidAsync/test/res/values/strings.xml
index ef0d9f7..ef0d9f7 100644
--- a/AndroidAsyncTest/res/values/strings.xml
+++ b/AndroidAsync/test/res/values/strings.xml
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/BodyTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/BodyTests.java
index e803849..e803849 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/BodyTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/BodyTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/ByteUtilTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/ByteUtilTests.java
index 0d2f5df..0d2f5df 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/ByteUtilTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/ByteUtilTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/CacheTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/CacheTests.java
index bffc34c..bffc34c 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/CacheTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/CacheTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/DnsTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/DnsTests.java
index 4c8f487..4c8f487 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/DnsTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/DnsTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/FileCacheTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/FileCacheTests.java
index ef07e27..ef07e27 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/FileCacheTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/FileCacheTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/FileTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/FileTests.java
index 1d37239..1d37239 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/FileTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/FileTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/FutureTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/FutureTests.java
index c453db9..c453db9 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/FutureTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/FutureTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpClientTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/HttpClientTests.java
index e238f66..6809880 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpClientTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/HttpClientTests.java
@@ -17,9 +17,11 @@ import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpClient.StringCallback;
import com.koushikdutta.async.http.AsyncHttpGet;
import com.koushikdutta.async.http.AsyncHttpHead;
+import com.koushikdutta.async.http.AsyncHttpPost;
import com.koushikdutta.async.http.AsyncHttpRequest;
import com.koushikdutta.async.http.AsyncHttpResponse;
import com.koushikdutta.async.http.ResponseCacheMiddleware;
+import com.koushikdutta.async.http.body.JSONObjectBody;
import com.koushikdutta.async.http.callback.HttpConnectCallback;
import com.koushikdutta.async.http.server.AsyncHttpServer;
import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
@@ -29,8 +31,9 @@ import com.koushikdutta.async.http.server.HttpServerRequestCallback;
import junit.framework.Assert;
import junit.framework.TestCase;
+import org.json.JSONObject;
+
import java.io.File;
-import java.net.URI;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
@@ -134,9 +137,8 @@ public class HttpClientTests extends TestCase {
// this testdata file was generated using /dev/random. filename is also the md5 of the file.
final static String dataNameAndHash = "6691924d7d24237d3b3679310157d640";
- final static String githubPath = "github.com/koush/AndroidAsync/raw/master/AndroidAsyncTest/testdata/";
+ final static String githubPath = "raw.githubusercontent.com/koush/AndroidAsync/master/AndroidAsync/test/assets/";
final static String github = "https://" + githubPath + dataNameAndHash;
- final static String githubInsecure = "http://" + githubPath + dataNameAndHash;
public void testGithubRandomData() throws Exception {
final Semaphore semaphore = new Semaphore(0);
final Md5 md5 = Md5.createInstance();
@@ -176,27 +178,6 @@ public class HttpClientTests extends TestCase {
assertEquals(md5.digest(), dataNameAndHash);
}
- public void testInsecureGithubRandomDataWithFuture() throws Exception {
- final Md5 md5 = Md5.createInstance();
- Future<ByteBufferList> bb = client.executeByteBufferList(new AsyncHttpGet(githubInsecure), null);
- md5.update(bb.get(TIMEOUT, TimeUnit.MILLISECONDS));
- assertEquals(md5.digest(), dataNameAndHash);
- }
-
- public void testInsecureGithubRandomDataWithFutureCallback() throws Exception {
- final Semaphore semaphore = new Semaphore(0);
- final Md5 md5 = Md5.createInstance();
- client.executeByteBufferList(new AsyncHttpGet(githubInsecure), null).setCallback(new FutureCallback<ByteBufferList>() {
- @Override
- public void onCompleted(Exception e, ByteBufferList bb) {
- md5.update(bb);
- semaphore.release();
- }
- });
- assertTrue("timeout", semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS));
- assertEquals(md5.digest(), dataNameAndHash);
- }
-
public void testGithubHelloWithFuture() throws Exception {
Future<String> string = client.executeString(new AsyncHttpGet("https://" + githubPath + "hello.txt"), null);
assertEquals(string.get(TIMEOUT, TimeUnit.MILLISECONDS), "hello world");
@@ -347,4 +328,13 @@ public class HttpClientTests extends TestCase {
Future<String> str = AsyncHttpClient.getDefaultInstance().executeString(req, null);
assertTrue(TextUtils.isEmpty(str.get(TIMEOUT, TimeUnit.MILLISECONDS)));
}
+
+ public void testPostJsonObject() throws Exception {
+ JSONObject post = new JSONObject();
+ post.put("ping", "pong");
+ AsyncHttpPost p = new AsyncHttpPost("https://koush.clockworkmod.com/test/echo");
+ p.setBody(new JSONObjectBody(post));
+ JSONObject ret = AsyncHttpClient.getDefaultInstance().executeJSONObject(p, null).get();
+ assertEquals("pong", ret.getString("ping"));
+ }
}
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/HttpServerTests.java
index df117e6..df117e6 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/HttpServerTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/Issue59.java b/AndroidAsync/test/src/com/koushikdutta/async/test/Issue59.java
index 44b44fc..44b44fc 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/Issue59.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/Issue59.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/Md5.java b/AndroidAsync/test/src/com/koushikdutta/async/test/Md5.java
index a6c4b18..a6c4b18 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/Md5.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/Md5.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/MultipartTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/MultipartTests.java
index cace2a5..cace2a5 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/MultipartTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/MultipartTests.java
diff --git a/AndroidAsync/test/src/com/koushikdutta/async/test/ParserTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/ParserTests.java
new file mode 100644
index 0000000..3374eff
--- /dev/null
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/ParserTests.java
@@ -0,0 +1,56 @@
+package com.koushikdutta.async.test;
+
+import com.koushikdutta.async.ByteBufferList;
+import com.koushikdutta.async.FilteredDataEmitter;
+import com.koushikdutta.async.future.Future;
+import com.koushikdutta.async.parser.StringParser;
+import com.koushikdutta.async.util.Charsets;
+
+import junit.framework.TestCase;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * Created by koush on 7/10/14.
+ */
+public class ParserTests extends TestCase {
+ public void testString() throws Exception {
+ StringParser p = new StringParser();
+ FilteredDataEmitter f = new FilteredDataEmitter() {
+ @Override
+ public boolean isPaused() {
+ return false;
+ }
+ };
+ Future<String> ret = p.parse(f);
+ ByteBufferList l = new ByteBufferList();
+ l.add(ByteBuffer.wrap("foo".getBytes(Charsets.US_ASCII.name())));
+ f.onDataAvailable(f, l);
+ f.getEndCallback().onCompleted(null);
+ String s = ret.get();
+ assertEquals(s, "foo");
+ }
+
+ public void testUtf8String() throws Exception {
+ StringParser p = new StringParser();
+ FilteredDataEmitter f = new FilteredDataEmitter() {
+ @Override
+ public String charset() {
+ return Charsets.UTF_8.name();
+ }
+
+ @Override
+ public boolean isPaused() {
+ return false;
+ }
+ };
+ Future<String> ret = p.parse(f);
+ ByteBufferList l = new ByteBufferList();
+ l.add(ByteBuffer.wrap("æææ".getBytes(Charsets.UTF_8.name())));
+ f.onDataAvailable(f, l);
+ f.getEndCallback().onCompleted(null);
+ String s = ret.get();
+ assertEquals(s, "æææ");
+ }
+}
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/ProxyTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/ProxyTests.java
index f7243d0..f7243d0 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/ProxyTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/ProxyTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/RedirectTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/RedirectTests.java
index def3e33..def3e33 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/RedirectTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/RedirectTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/SSLTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/SSLTests.java
index 4e89b37..fbdc6cf 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/SSLTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/SSLTests.java
@@ -3,7 +3,6 @@ package com.koushikdutta.async.test;
import android.test.AndroidTestCase;
import com.koushikdutta.async.AsyncServer;
-import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpGet;
import com.koushikdutta.async.http.server.AsyncHttpServer;
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/SanityChecks.java b/AndroidAsync/test/src/com/koushikdutta/async/test/SanityChecks.java
index 69cc566..69cc566 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/SanityChecks.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/SanityChecks.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/SocketIOTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/SocketIOTests.java
index 4c8ec66..4c8ec66 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/SocketIOTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/SocketIOTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/TimeoutTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/TimeoutTests.java
index 2eb13b4..2eb13b4 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/TimeoutTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/TimeoutTests.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/TriggerFuture.java b/AndroidAsync/test/src/com/koushikdutta/async/test/TriggerFuture.java
index eab00ed..eab00ed 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/TriggerFuture.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/TriggerFuture.java
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/WebSocketTests.java b/AndroidAsync/test/src/com/koushikdutta/async/test/WebSocketTests.java
index a5a7f92..a5a7f92 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/WebSocketTests.java
+++ b/AndroidAsync/test/src/com/koushikdutta/async/test/WebSocketTests.java
diff --git a/AndroidAsyncTest/.classpath b/AndroidAsyncTest/.classpath
deleted file mode 100644
index 6982030..0000000
--- a/AndroidAsyncTest/.classpath
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry combineaccessrules="false" kind="src" path="/AndroidAsyncSample"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="gen"/>
- <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
- <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/AndroidAsyncTest/.project b/AndroidAsyncTest/.project
deleted file mode 100644
index 379c28d..0000000
--- a/AndroidAsyncTest/.project
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>AndroidAsyncTest</name>
- <comment></comment>
- <projects>
- <project>AndroidAsyncSample</project>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.ApkBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/AndroidAsyncTest/AndroidAsyncTest.iml b/AndroidAsyncTest/AndroidAsyncTest.iml
deleted file mode 100644
index fb8467f..0000000
--- a/AndroidAsyncTest/AndroidAsyncTest.iml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="FacetManager">
- <facet type="android" name="Android">
- <configuration>
- <option name="UPDATE_PROPERTY_FILES" value="true" />
- <notImportedProperties>
- <property>MANIFEST_FILE_PATH</property>
- <property>RESOURCES_DIR_PATH</property>
- <property>ASSETS_DIR_PATH</property>
- <property>NATIVE_LIBS_DIR_PATH</property>
- </notImportedProperties>
- </configuration>
- </facet>
- </component>
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="AndroidAsync" />
- </component>
-</module>
-
diff --git a/AndroidAsyncTest/AndroidManifest.xml b/AndroidAsyncTest/AndroidManifest.xml
deleted file mode 100644
index 1c36b17..0000000
--- a/AndroidAsyncTest/AndroidManifest.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.koushikdutta.async.test"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
- <instrumentation
- android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.koushikdutta.async.test" />
-
- <application
- android:debuggable="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
- <uses-library android:name="android.test.runner" />
- </application>
-
-</manifest> \ No newline at end of file
diff --git a/AndroidAsyncTest/proguard-project.txt b/AndroidAsyncTest/proguard-project.txt
deleted file mode 100644
index f2fe155..0000000
--- a/AndroidAsyncTest/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/AndroidAsyncTest/project.properties b/AndroidAsyncTest/project.properties
deleted file mode 100644
index 7e931bf..0000000
--- a/AndroidAsyncTest/project.properties
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-19
-android.library.reference.1=../AndroidAsync
diff --git a/README.md b/README.md
index 6c86ae6..042c091 100644
--- a/README.md
+++ b/README.md
@@ -137,7 +137,7 @@ AsyncHttpClient.getDefaultInstance().websocket(get, "my-protocol", new WebSocket
```
-### AndroidAsync also supports socket.io
+### AndroidAsync also supports socket.io (version 0.9.x)
```java
SocketIOClient.connect(AsyncHttpClient.getDefaultInstance(), "http://192.168.1.2:3000", new ConnectCallback() {