Skip to content

Commit 9473c0e

Browse files
committed
ByteBuffer List fixes:
Stop assuming everything is array backed. readString/peekString refactor. Default charset is ascii. SSL: Conscrypt an SPDY prep.
1 parent d8a5060 commit 9473c0e

File tree

12 files changed

+134
-78
lines changed

12 files changed

+134
-78
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ build
88
.DS_Store
99

1010
okhttp
11+
okio

AndroidAsync/AndroidAsync-AndroidAsync.iml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
6161
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
6262
</content>
63+
<content url="file://$MODULE_DIR$/../compat">
64+
<sourceFolder url="file://$MODULE_DIR$/../compat" isTestSource="false" />
65+
</content>
66+
<content url="file://$MODULE_DIR$/../conscrypt">
67+
<sourceFolder url="file://$MODULE_DIR$/../conscrypt" isTestSource="false" />
68+
</content>
6369
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
6470
<orderEntry type="sourceFolder" forTests="false" />
6571
</component>

AndroidAsync/build.gradle

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,36 @@ buildscript {
99
apply plugin: 'com.android.library'
1010

1111
android {
12+
dependencies {
13+
// compile 'com.squareup.okio:okio:+'
14+
// androidTestCompile 'com.squareup.okhttp:okhttp:1.+'
15+
}
16+
1217
sourceSets {
1318
main {
1419
manifest.srcFile 'AndroidManifest.xml'
1520

16-
java.srcDirs=['src/']
21+
jniLibs.srcDirs = ['libs/']
22+
23+
java.srcDirs=['src/'
24+
// , 'okhttp/'
25+
// , 'okhttp-shim/'
26+
// , '../okio/okio/src/main/java/'
27+
, '../conscrypt/'
28+
, '../compat/'
29+
// , '../okhttp/okhttp/src/main/java/'
30+
]
1731
}
1832
androidTest.java.srcDirs=['test/src/']
1933
androidTest.res.srcDirs=['test/res/']
2034
androidTest.assets.srcDirs=['test/assets/']
2135
}
2236

37+
compileOptions {
38+
sourceCompatibility JavaVersion.VERSION_1_7
39+
targetCompatibility JavaVersion.VERSION_1_7
40+
}
41+
2342
compileSdkVersion 19
2443
buildToolsVersion "20.0.0"
2544
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import java.security.cert.X509Certificate;
44

5+
import javax.net.ssl.SSLEngine;
6+
57
public interface AsyncSSLSocket extends AsyncSocket {
68
public X509Certificate[] getPeerCertificates();
9+
public SSLEngine getSSLEngine();
710
}

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,23 @@ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, Strin
9090
}
9191
}
9292

93-
public static SSLEngine createDefaultSSLEngine() {
94-
return defaultSSLContext.createSSLEngine();
93+
public static SSLContext getDefaultSSLContext() {
94+
return defaultSSLContext;
9595
}
9696

9797
public static void handshake(AsyncSocket socket,
9898
String host, int port,
9999
SSLEngine sslEngine,
100100
TrustManager[] trustManagers, HostnameVerifier verifier, boolean clientMode,
101-
HandshakeCallback callback) {
101+
final HandshakeCallback callback) {
102102
AsyncSSLSocketWrapper wrapper = new AsyncSSLSocketWrapper(socket, host, port, sslEngine, trustManagers, verifier, clientMode);
103103
wrapper.handshakeCallback = callback;
104+
socket.setClosedCallback(new CompletedCallback() {
105+
@Override
106+
public void onCompleted(Exception ex) {
107+
callback.onHandshakeCompleted(new SSLException(ex), null);
108+
}
109+
});
104110
try {
105111
wrapper.engine.beginHandshake();
106112
wrapper.handleHandshakeStatus(wrapper.engine.getHandshakeStatus());
@@ -202,6 +208,11 @@ else if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
202208
});
203209
}
204210

211+
@Override
212+
public SSLEngine getSSLEngine() {
213+
return engine;
214+
}
215+
205216
void addToPending(ByteBufferList out, ByteBuffer mReadTmp) {
206217
mReadTmp.flip();
207218
if (mReadTmp.hasRemaining()) {

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

Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import com.koushikdutta.async.util.Charsets;
88

9+
import java.io.IOException;
10+
import java.io.OutputStream;
911
import java.nio.ByteBuffer;
1012
import java.nio.ByteOrder;
1113
import java.nio.charset.Charset;
@@ -47,9 +49,12 @@ public void addAll(ByteBuffer... bb) {
4749
public byte[] getAllByteArray() {
4850
// fast path to return the contents of the first and only byte buffer,
4951
// if that's what we're looking for. avoids allocation.
50-
if (mBuffers.size() == 1 && mBuffers.peek().capacity() == remaining()) {
51-
remaining = 0;
52-
return mBuffers.remove().array();
52+
if (mBuffers.size() == 1) {
53+
ByteBuffer peek = mBuffers.peek();
54+
if (peek.capacity() == remaining() && peek.isDirect()) {
55+
remaining = 0;
56+
return mBuffers.remove().array();
57+
}
5358
}
5459

5560
byte[] ret = new byte[remaining()];
@@ -206,46 +211,7 @@ private ByteBuffer read(int count) {
206211
return first.order(order);
207212
}
208213

209-
ByteBuffer ret = null;
210-
int retOffset = 0;
211-
int allocSize = 0;
212-
213-
// attempt to find a buffer that can fit this, and the necessary
214-
// alloc size to not leave anything leftover in the final buffer.
215-
for (ByteBuffer b: mBuffers) {
216-
if (allocSize >= count)
217-
break;
218-
// see if this fits...
219-
if ((ret == null || b.capacity() > ret.capacity()) && b.capacity() >= count) {
220-
ret = b;
221-
retOffset = allocSize;
222-
}
223-
allocSize += b.remaining();
224-
}
225-
226-
if (ret != null && ret.capacity() > allocSize) {
227-
// move the current contents of the target bytebuffer around to its final position
228-
System.arraycopy(ret.array(), ret.arrayOffset() + ret.position(), ret.array(), ret.arrayOffset() + retOffset, ret.remaining());
229-
int retRemaining = ret.remaining();
230-
ret.position(0);
231-
ret.limit(allocSize);
232-
allocSize = 0;
233-
while (allocSize < count) {
234-
ByteBuffer b = mBuffers.remove();
235-
if (b != ret) {
236-
System.arraycopy(b.array(), b.arrayOffset() + b.position(), ret.array(), ret.arrayOffset() + allocSize, b.remaining());
237-
allocSize += b.remaining();
238-
reclaim(b);
239-
}
240-
else {
241-
allocSize += retRemaining;
242-
}
243-
}
244-
mBuffers.addFirst(ret);
245-
return ret.order(order);
246-
}
247-
248-
ret = obtain(count);
214+
ByteBuffer ret = obtain(count);
249215
ret.limit(count);
250216
byte[] bytes = ret.array();
251217
int offset = 0;
@@ -349,30 +315,43 @@ public void spewString() {
349315
System.out.println(peekString());
350316
}
351317

352-
// not doing toString as this is really nasty in the debugger...
353318
public String peekString() {
319+
return peekString(null);
320+
}
321+
322+
// not doing toString as this is really nasty in the debugger...
323+
public String peekString(Charset charset) {
324+
if (charset == null)
325+
charset = Charsets.US_ASCII;
354326
StringBuilder builder = new StringBuilder();
355327
for (ByteBuffer bb: mBuffers) {
356-
builder.append(new String(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()));
328+
byte[] bytes;
329+
int offset;
330+
int length;
331+
if (bb.isDirect()) {
332+
bytes = new byte[bb.remaining()];
333+
offset = 0;
334+
length = bb.remaining();
335+
bb.get(bytes);
336+
}
337+
else {
338+
bytes = bb.array();
339+
offset = bb.arrayOffset() + bb.position();
340+
length = bb.remaining();
341+
}
342+
builder.append(new String(bytes, offset, length, charset));
357343
}
358344
return builder.toString();
359345
}
360346

361347
public String readString() {
362-
return readString(Charsets.US_ASCII);
348+
return readString(null);
363349
}
364350

365351
public String readString(Charset charset) {
366-
if (charset == null)
367-
charset = Charset.defaultCharset();
368-
StringBuilder builder = new StringBuilder();
369-
while (mBuffers.size() > 0) {
370-
ByteBuffer bb = mBuffers.remove();
371-
builder.append(new String(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining(), charset));
372-
reclaim(bb);
373-
}
374-
remaining = 0;
375-
return builder.toString();
352+
String ret = peekString(charset);
353+
recycle();
354+
return ret;
376355
}
377356

378357
static class Reclaimer implements Comparator<ByteBuffer> {
@@ -512,4 +491,22 @@ public static void obtainArray(ByteBuffer[] arr, int size) {
512491
}
513492

514493
public static final ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
494+
495+
public static void writeOutputStream(OutputStream out, ByteBuffer b) throws IOException {
496+
byte[] bytes;
497+
int offset;
498+
int length;
499+
if (b.isDirect()) {
500+
bytes = new byte[b.remaining()];
501+
offset = 0;
502+
length = b.remaining();
503+
b.get(bytes);
504+
}
505+
else {
506+
bytes = b.array();
507+
offset = b.arrayOffset() + b.position();
508+
length = b.remaining();
509+
}
510+
out.write(bytes, offset, length);
511+
}
515512
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public ByteBufferList filter(ByteBufferList bb) {
5050
if (bb != null) {
5151
while (bb.size() > 0) {
5252
ByteBuffer b = bb.remove();
53-
zop.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
53+
ByteBufferList.writeOutputStream(zop, b);
5454
ByteBufferList.reclaim(b);
5555
}
5656
}

AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.koushikdutta.async.http;
22

33
import android.net.Uri;
4-
import android.os.Build;
54
import android.text.TextUtils;
65

76
import com.koushikdutta.async.AsyncSSLSocket;
@@ -14,15 +13,13 @@
1413
import com.koushikdutta.async.http.libcore.RawHeaders;
1514

1615
import java.io.IOException;
17-
import java.security.cert.X509Certificate;
1816
import java.util.ArrayList;
1917
import java.util.List;
2018

2119
import javax.net.ssl.HostnameVerifier;
2220
import javax.net.ssl.SSLContext;
2321
import javax.net.ssl.SSLEngine;
2422
import javax.net.ssl.TrustManager;
25-
import javax.net.ssl.X509TrustManager;
2623

2724
public class AsyncSSLSocketMiddleware extends AsyncSocketMiddleware {
2825
public AsyncSSLSocketMiddleware(AsyncHttpClient client) {
@@ -35,6 +32,10 @@ public void setSSLContext(SSLContext sslContext) {
3532
this.sslContext = sslContext;
3633
}
3734

35+
public SSLContext getSSLContext() {
36+
return sslContext != null ? sslContext : AsyncSSLSocketWrapper.getDefaultSSLContext();
37+
}
38+
3839
TrustManager[] trustManagers;
3940

4041
public void setTrustManagers(TrustManager[] trustManagers) {
@@ -47,7 +48,7 @@ public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
4748
this.hostnameVerifier = hostnameVerifier;
4849
}
4950

50-
List<AsyncSSLEngineConfigurator> engineConfigurators = new ArrayList<AsyncSSLEngineConfigurator>();
51+
protected List<AsyncSSLEngineConfigurator> engineConfigurators = new ArrayList<AsyncSSLEngineConfigurator>();
5152

5253
public void addEngineConfigurator(AsyncSSLEngineConfigurator engineConfigurator) {
5354
engineConfigurators.add(engineConfigurator);
@@ -58,11 +59,8 @@ public void clearEngineConfigurators() {
5859
}
5960

6061
protected SSLEngine createConfiguredSSLEngine(String host, int port) {
61-
SSLEngine sslEngine;
62-
if (sslContext != null)
63-
sslEngine = sslContext.createSSLEngine();
64-
else
65-
sslEngine = AsyncSSLSocketWrapper.createDefaultSSLEngine();
62+
SSLContext sslContext = getSSLContext();
63+
SSLEngine sslEngine = sslContext.createSSLEngine();
6664

6765
for (AsyncSSLEngineConfigurator configurator : engineConfigurators) {
6866
configurator.configureEngine(sslEngine, host, port);
@@ -71,15 +69,20 @@ protected SSLEngine createConfiguredSSLEngine(String host, int port) {
7169
return sslEngine;
7270
}
7371

74-
protected void tryHandshake(final ConnectCallback callback, AsyncSocket socket, final Uri uri, final int port) {
75-
AsyncSSLSocketWrapper.handshake(socket, uri.getHost(), port,
76-
createConfiguredSSLEngine(uri.getHost(), port),
77-
trustManagers, hostnameVerifier, true, new AsyncSSLSocketWrapper.HandshakeCallback() {
72+
protected AsyncSSLSocketWrapper.HandshakeCallback createHandshakeCallback(final ConnectCallback callback) {
73+
return new AsyncSSLSocketWrapper.HandshakeCallback() {
7874
@Override
7975
public void onHandshakeCompleted(Exception e, AsyncSSLSocket socket) {
8076
callback.onConnectCompleted(e, socket);
8177
}
82-
});
78+
};
79+
}
80+
81+
protected void tryHandshake(final ConnectCallback callback, AsyncSocket socket, final Uri uri, final int port) {
82+
AsyncSSLSocketWrapper.handshake(socket, uri.getHost(), port,
83+
createConfiguredSSLEngine(uri.getHost(), port),
84+
trustManagers, hostnameVerifier, true,
85+
createHandshakeCallback(callback));
8386
}
8487

8588
@Override

AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import java.util.List;
4444
import java.util.Map;
4545

46+
import javax.net.ssl.SSLEngine;
47+
4648
public class ResponseCacheMiddleware extends SimpleMiddleware {
4749
public static final int ENTRY_METADATA = 0;
4850
public static final int ENTRY_BODY = 1;
@@ -339,7 +341,7 @@ public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
339341
while (!bb.isEmpty()) {
340342
ByteBuffer b = bb.remove();
341343
try {
342-
outputStream.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
344+
ByteBufferList.writeOutputStream(outputStream, b);
343345
}
344346
finally {
345347
copy.add(b);
@@ -676,6 +678,11 @@ public CachedSSLSocket(EntryCacheResponse cacheResponse, long contentLength) {
676678
super(cacheResponse, contentLength);
677679
}
678680

681+
@Override
682+
public SSLEngine getSSLEngine() {
683+
return null;
684+
}
685+
679686
@Override
680687
public X509Certificate[] getPeerCertificates() {
681688
return null;

0 commit comments

Comments
 (0)