use of com.koushikdutta.async.callback.ConnectCallback in project AndroidAsync by koush.
the class AsyncSocketMiddleware method getSocket.
@Override
public Cancellable getSocket(final GetSocketData data) {
final Uri uri = data.request.getUri();
final int port = getSchemePort(data.request.getUri());
if (port == -1) {
return null;
}
data.state.put("socket-owner", this);
final String lookup = computeLookup(uri, port, data.request.getProxyHost(), data.request.getProxyPort());
ConnectionInfo info = getOrCreateConnectionInfo(lookup);
synchronized (AsyncSocketMiddleware.this) {
if (info.openCount >= maxConnectionCount) {
// wait for a connection queue to free up
SimpleCancellable queueCancel = new SimpleCancellable();
info.queue.add(data);
return queueCancel;
}
info.openCount++;
while (!info.sockets.isEmpty()) {
IdleSocketHolder idleSocketHolder = info.sockets.pop();
final AsyncSocket socket = idleSocketHolder.socket;
if (idleSocketHolder.idleTime + idleTimeoutMs < System.currentTimeMillis()) {
socket.setClosedCallback(null);
socket.close();
continue;
}
if (!socket.isOpen())
continue;
data.request.logd("Reusing keep-alive socket");
data.connectCallback.onConnectCompleted(null, socket);
// just a noop/dummy, as this can't actually be cancelled.
SimpleCancellable ret = new SimpleCancellable();
ret.setComplete();
return ret;
}
}
if (!connectAllAddresses || proxyHost != null || data.request.getProxyHost() != null) {
// just default to connecting to a single address
data.request.logd("Connecting socket");
String unresolvedHost;
int unresolvedPort;
boolean proxied = false;
if (data.request.getProxyHost() == null && proxyHost != null)
data.request.enableProxy(proxyHost, proxyPort);
if (data.request.getProxyHost() != null) {
unresolvedHost = data.request.getProxyHost();
unresolvedPort = data.request.getProxyPort();
proxied = true;
} else {
unresolvedHost = uri.getHost();
unresolvedPort = port;
}
if (proxied) {
data.request.logv("Using proxy: " + unresolvedHost + ":" + unresolvedPort);
}
return mClient.getServer().connectSocket(unresolvedHost, unresolvedPort, wrapCallback(data, uri, port, proxied, data.connectCallback));
}
// try to connect to everything...
data.request.logv("Resolving domain and connecting to all available addresses");
return mClient.getServer().getAllByName(uri.getHost()).then(new TransformFuture<AsyncSocket, InetAddress[]>() {
Exception lastException;
@Override
protected void error(Exception e) {
super.error(e);
wrapCallback(data, uri, port, false, data.connectCallback).onConnectCompleted(e, null);
}
@Override
protected void transform(final InetAddress[] result) throws Exception {
Continuation keepTrying = new Continuation(new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
// if it completed, that means that the connection failed
if (lastException == null)
lastException = new ConnectionFailedException("Unable to connect to remote address");
if (setComplete(lastException)) {
wrapCallback(data, uri, port, false, data.connectCallback).onConnectCompleted(lastException, null);
}
}
});
for (final InetAddress address : result) {
final String inetSockAddress = String.format(Locale.ENGLISH, "%s:%s", address, port);
keepTrying.add(new ContinuationCallback() {
@Override
public void onContinue(Continuation continuation, final CompletedCallback next) throws Exception {
data.request.logv("attempting connection to " + inetSockAddress);
mClient.getServer().connectSocket(new InetSocketAddress(address, port), wrapCallback(data, uri, port, false, new ConnectCallback() {
@Override
public void onConnectCompleted(Exception ex, AsyncSocket socket) {
if (isDone()) {
lastException = new Exception("internal error during connect to " + inetSockAddress);
next.onCompleted(null);
return;
}
// try the next address
if (ex != null) {
lastException = ex;
next.onCompleted(null);
return;
}
// if the socket is no longer needed, just hang onto it...
if (isDone() || isCancelled()) {
data.request.logd("Recycling extra socket leftover from cancelled operation");
idleSocket(socket);
recycleSocket(socket, data.request);
return;
}
if (setComplete(null, socket)) {
data.connectCallback.onConnectCompleted(null, socket);
}
}
}));
}
});
}
keepTrying.start();
}
});
}
use of com.koushikdutta.async.callback.ConnectCallback in project AndroidAsync by koush.
the class AsyncHttpClient method executeAffinity.
private void executeAffinity(final AsyncHttpRequest request, final int redirectCount, final FutureAsyncHttpResponse cancel, final HttpConnectCallback callback) {
assert mServer.isAffinityThread();
if (redirectCount > 15) {
reportConnectedCompleted(cancel, new RedirectLimitExceededException("too many redirects"), null, request, callback);
return;
}
final Uri uri = request.getUri();
final AsyncHttpClientMiddleware.OnResponseCompleteDataOnRequestSentData data = new AsyncHttpClientMiddleware.OnResponseCompleteDataOnRequestSentData();
request.executionTime = System.currentTimeMillis();
data.request = request;
request.logd("Executing request.");
for (AsyncHttpClientMiddleware middleware : mMiddleware) {
middleware.onRequest(data);
}
if (request.getTimeout() > 0) {
// set connect timeout
cancel.timeoutRunnable = new Runnable() {
@Override
public void run() {
// we've timed out, kill the connections
if (data.socketCancellable != null) {
data.socketCancellable.cancel();
if (data.socket != null)
data.socket.close();
}
reportConnectedCompleted(cancel, new TimeoutException(), null, request, callback);
}
};
cancel.scheduled = mServer.postDelayed(cancel.timeoutRunnable, getTimeoutRemaining(request));
}
// 2) wait for a connect
data.connectCallback = new ConnectCallback() {
boolean reported;
@Override
public void onConnectCompleted(Exception ex, AsyncSocket socket) {
if (reported) {
if (socket != null) {
socket.setDataCallback(new DataCallback.NullDataCallback());
socket.setEndCallback(new CompletedCallback.NullCompletedCallback());
socket.close();
throw new AssertionError("double connect callback");
}
}
reported = true;
request.logv("socket connected");
if (cancel.isCancelled()) {
if (socket != null)
socket.close();
return;
}
// 3) on connect, cancel timeout
if (cancel.timeoutRunnable != null)
mServer.removeAllCallbacks(cancel.scheduled);
if (ex != null) {
reportConnectedCompleted(cancel, ex, null, request, callback);
return;
}
data.socket = socket;
cancel.socket = socket;
executeSocket(request, redirectCount, cancel, callback, data);
}
};
// set up the system default proxy and connect
setupAndroidProxy(request);
// set the implicit content type
if (request.getBody() != null) {
if (request.getHeaders().get("Content-Type") == null)
request.getHeaders().set("Content-Type", request.getBody().getContentType());
}
final Exception unsupportedURI;
for (AsyncHttpClientMiddleware middleware : mMiddleware) {
Cancellable socketCancellable = middleware.getSocket(data);
if (socketCancellable != null) {
data.socketCancellable = socketCancellable;
cancel.setParent(socketCancellable);
return;
}
}
unsupportedURI = new IllegalArgumentException("invalid uri=" + request.getUri() + " middlewares=" + mMiddleware);
reportConnectedCompleted(cancel, unsupportedURI, null, request, callback);
}
use of com.koushikdutta.async.callback.ConnectCallback in project AndroidAsync by koush.
the class AsyncSSLSocketMiddleware method wrapCallback.
@Override
protected ConnectCallback wrapCallback(final GetSocketData data, final Uri uri, final int port, final boolean proxied, final ConnectCallback callback) {
return new ConnectCallback() {
@Override
public void onConnectCompleted(Exception ex, final AsyncSocket socket) {
if (ex != null) {
callback.onConnectCompleted(ex, socket);
return;
}
if (!proxied) {
tryHandshake(socket, data, uri, port, callback);
return;
}
// this SSL connection is proxied, must issue a CONNECT request to the proxy server
// http://stackoverflow.com/a/6594880/704837
// some proxies also require 'Host' header, it should be safe to provide it every time
String connect = String.format(Locale.ENGLISH, "CONNECT %s:%s HTTP/1.1\r\nHost: %s\r\n\r\n", uri.getHost(), port, uri.getHost());
data.request.logv("Proxying: " + connect);
Util.writeAll(socket, connect.getBytes(), new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
if (ex != null) {
callback.onConnectCompleted(ex, socket);
return;
}
LineEmitter liner = new LineEmitter();
liner.setLineCallback(new LineEmitter.StringCallback() {
String statusLine;
@Override
public void onStringAvailable(String s) {
data.request.logv(s);
if (statusLine == null) {
statusLine = s.trim();
if (!statusLine.matches("HTTP/1.\\d 2\\d\\d .*")) {
// connect response is allowed to have any 2xx status code
socket.setDataCallback(null);
socket.setEndCallback(null);
callback.onConnectCompleted(new IOException("non 2xx status line: " + statusLine), socket);
}
} else if (TextUtils.isEmpty(s.trim())) {
// skip all headers, complete handshake once empty line is received
socket.setDataCallback(null);
socket.setEndCallback(null);
tryHandshake(socket, data, uri, port, callback);
}
}
});
socket.setDataCallback(liner);
socket.setEndCallback(new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
if (!socket.isOpen() && ex == null)
ex = new IOException("socket closed before proxy connect response");
callback.onConnectCompleted(ex, socket);
}
});
}
});
}
};
}
use of com.koushikdutta.async.callback.ConnectCallback in project AndroidAsync by koush.
the class DnsTests method testNoDomain.
public void testNoDomain() throws Exception {
AsyncServer server = new AsyncServer();
try {
final Semaphore semaphore = new Semaphore(0);
server.connectSocket("www.clockworkmod-notfound.com", 8080, new ConnectCallback() {
@Override
public void onConnectCompleted(Exception ex, AsyncSocket socket) {
assertTrue(ex instanceof UnknownHostException);
semaphore.release();
}
});
assertTrue(semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS));
} finally {
server.stop();
}
}
use of com.koushikdutta.async.callback.ConnectCallback in project AndroidAsync by koush.
the class SpdyMiddleware method wrapCallback.
@Override
protected ConnectCallback wrapCallback(final GetSocketData data, final Uri uri, final int port, final boolean proxied, ConnectCallback callback) {
final ConnectCallback superCallback = super.wrapCallback(data, uri, port, proxied, callback);
final String key = data.state.get("spdykey");
if (key == null)
return superCallback;
// new outgoing connection, try to make this a spdy connection
return new ConnectCallback() {
@Override
public void onConnectCompleted(Exception ex, AsyncSocket socket) {
// trigger the waiters
if (ex != null) {
final SpdyConnectionWaiter conn = connections.remove(key);
if (conn != null)
conn.setComplete(ex);
}
superCallback.onConnectCompleted(ex, socket);
}
};
}
Aggregations