You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/06/11 02:04:16 UTC
[40/52] [partial] start of lazy loading: axe all vendored-in libs
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
deleted file mode 100644
index ce0a71d..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2012 Square, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.okhttp.internal.http;
-
-import com.squareup.okhttp.Address;
-import com.squareup.okhttp.Connection;
-import com.squareup.okhttp.ConnectionPool;
-import com.squareup.okhttp.Route;
-import com.squareup.okhttp.internal.Dns;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.ProxySelector;
-import java.net.SocketAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import javax.net.ssl.SSLHandshakeException;
-
-import static com.squareup.okhttp.internal.Util.getEffectivePort;
-
-/**
- * Selects routes to connect to an origin server. Each connection requires a
- * choice of proxy server, IP address, and TLS mode. Connections may also be
- * recycled.
- */
-public final class RouteSelector {
- /** Uses {@link com.squareup.okhttp.internal.Platform#enableTlsExtensions}. */
- private static final int TLS_MODE_MODERN = 1;
- /** Uses {@link com.squareup.okhttp.internal.Platform#supportTlsIntolerantServer}. */
- private static final int TLS_MODE_COMPATIBLE = 0;
- /** No TLS mode. */
- private static final int TLS_MODE_NULL = -1;
-
- private final Address address;
- private final URI uri;
- private final ProxySelector proxySelector;
- private final ConnectionPool pool;
- private final Dns dns;
- private final Set<Route> failedRoutes;
-
- /* The most recently attempted route. */
- private Proxy lastProxy;
- private InetSocketAddress lastInetSocketAddress;
-
- /* State for negotiating the next proxy to use. */
- private boolean hasNextProxy;
- private Proxy userSpecifiedProxy;
- private Iterator<Proxy> proxySelectorProxies;
-
- /* State for negotiating the next InetSocketAddress to use. */
- private InetAddress[] socketAddresses;
- private int nextSocketAddressIndex;
- private int socketPort;
-
- /* State for negotiating the next TLS configuration */
- private int nextTlsMode = TLS_MODE_NULL;
-
- /* State for negotiating failed routes */
- private final List<Route> postponedRoutes;
-
- public RouteSelector(Address address, URI uri, ProxySelector proxySelector, ConnectionPool pool,
- Dns dns, Set<Route> failedRoutes) {
- this.address = address;
- this.uri = uri;
- this.proxySelector = proxySelector;
- this.pool = pool;
- this.dns = dns;
- this.failedRoutes = failedRoutes;
- this.postponedRoutes = new LinkedList<Route>();
-
- resetNextProxy(uri, address.getProxy());
- }
-
- /**
- * Returns true if there's another route to attempt. Every address has at
- * least one route.
- */
- public boolean hasNext() {
- return hasNextTlsMode() || hasNextInetSocketAddress() || hasNextProxy() || hasNextPostponed();
- }
-
- /**
- * Returns the next route address to attempt.
- *
- * @throws NoSuchElementException if there are no more routes to attempt.
- */
- public Connection next() throws IOException {
- // Always prefer pooled connections over new connections.
- Connection pooled = pool.get(address);
- if (pooled != null) {
- return pooled;
- }
-
- // Compute the next route to attempt.
- if (!hasNextTlsMode()) {
- if (!hasNextInetSocketAddress()) {
- if (!hasNextProxy()) {
- if (!hasNextPostponed()) {
- throw new NoSuchElementException();
- }
- return new Connection(nextPostponed());
- }
- lastProxy = nextProxy();
- resetNextInetSocketAddress(lastProxy);
- }
- lastInetSocketAddress = nextInetSocketAddress();
- resetNextTlsMode();
- }
-
- boolean modernTls = nextTlsMode() == TLS_MODE_MODERN;
- Route route = new Route(address, lastProxy, lastInetSocketAddress, modernTls);
- if (failedRoutes.contains(route)) {
- postponedRoutes.add(route);
- // We will only recurse in order to skip previously failed routes. They will be
- // tried last.
- return next();
- }
-
- return new Connection(route);
- }
-
- /**
- * Clients should invoke this method when they encounter a connectivity
- * failure on a connection returned by this route selector.
- */
- public void connectFailed(Connection connection, IOException failure) {
- Route failedRoute = connection.getRoute();
- if (failedRoute.getProxy().type() != Proxy.Type.DIRECT && proxySelector != null) {
- // Tell the proxy selector when we fail to connect on a fresh connection.
- proxySelector.connectFailed(uri, failedRoute.getProxy().address(), failure);
- }
-
- failedRoutes.add(failedRoute);
- if (!(failure instanceof SSLHandshakeException)) {
- // If the problem was not related to SSL then it will also fail with
- // a different Tls mode therefore we can be proactive about it.
- failedRoutes.add(failedRoute.flipTlsMode());
- }
- }
-
- /** Resets {@link #nextProxy} to the first option. */
- private void resetNextProxy(URI uri, Proxy proxy) {
- this.hasNextProxy = true; // This includes NO_PROXY!
- if (proxy != null) {
- this.userSpecifiedProxy = proxy;
- } else {
- List<Proxy> proxyList = proxySelector.select(uri);
- if (proxyList != null) {
- this.proxySelectorProxies = proxyList.iterator();
- }
- }
- }
-
- /** Returns true if there's another proxy to try. */
- private boolean hasNextProxy() {
- return hasNextProxy;
- }
-
- /** Returns the next proxy to try. May be PROXY.NO_PROXY but never null. */
- private Proxy nextProxy() {
- // If the user specifies a proxy, try that and only that.
- if (userSpecifiedProxy != null) {
- hasNextProxy = false;
- return userSpecifiedProxy;
- }
-
- // Try each of the ProxySelector choices until one connection succeeds. If none succeed
- // then we'll try a direct connection below.
- if (proxySelectorProxies != null) {
- while (proxySelectorProxies.hasNext()) {
- Proxy candidate = proxySelectorProxies.next();
- if (candidate.type() != Proxy.Type.DIRECT) {
- return candidate;
- }
- }
- }
-
- // Finally try a direct connection.
- hasNextProxy = false;
- return Proxy.NO_PROXY;
- }
-
- /** Resets {@link #nextInetSocketAddress} to the first option. */
- private void resetNextInetSocketAddress(Proxy proxy) throws UnknownHostException {
- socketAddresses = null; // Clear the addresses. Necessary if getAllByName() below throws!
-
- String socketHost;
- if (proxy.type() == Proxy.Type.DIRECT) {
- socketHost = uri.getHost();
- socketPort = getEffectivePort(uri);
- } else {
- SocketAddress proxyAddress = proxy.address();
- if (!(proxyAddress instanceof InetSocketAddress)) {
- throw new IllegalArgumentException(
- "Proxy.address() is not an " + "InetSocketAddress: " + proxyAddress.getClass());
- }
- InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
- socketHost = proxySocketAddress.getHostName();
- socketPort = proxySocketAddress.getPort();
- }
-
- // Try each address for best behavior in mixed IPv4/IPv6 environments.
- socketAddresses = dns.getAllByName(socketHost);
- nextSocketAddressIndex = 0;
- }
-
- /** Returns true if there's another socket address to try. */
- private boolean hasNextInetSocketAddress() {
- return socketAddresses != null;
- }
-
- /** Returns the next socket address to try. */
- private InetSocketAddress nextInetSocketAddress() throws UnknownHostException {
- InetSocketAddress result =
- new InetSocketAddress(socketAddresses[nextSocketAddressIndex++], socketPort);
- if (nextSocketAddressIndex == socketAddresses.length) {
- socketAddresses = null; // So that hasNextInetSocketAddress() returns false.
- nextSocketAddressIndex = 0;
- }
-
- return result;
- }
-
- /** Resets {@link #nextTlsMode} to the first option. */
- private void resetNextTlsMode() {
- nextTlsMode = (address.getSslSocketFactory() != null) ? TLS_MODE_MODERN : TLS_MODE_COMPATIBLE;
- }
-
- /** Returns true if there's another TLS mode to try. */
- private boolean hasNextTlsMode() {
- return nextTlsMode != TLS_MODE_NULL;
- }
-
- /** Returns the next TLS mode to try. */
- private int nextTlsMode() {
- if (nextTlsMode == TLS_MODE_MODERN) {
- nextTlsMode = TLS_MODE_COMPATIBLE;
- return TLS_MODE_MODERN;
- } else if (nextTlsMode == TLS_MODE_COMPATIBLE) {
- nextTlsMode = TLS_MODE_NULL; // So that hasNextTlsMode() returns false.
- return TLS_MODE_COMPATIBLE;
- } else {
- throw new AssertionError();
- }
- }
-
- /** Returns true if there is another postponed route to try. */
- private boolean hasNextPostponed() {
- return !postponedRoutes.isEmpty();
- }
-
- /** Returns the next postponed route to try. */
- private Route nextPostponed() {
- return postponedRoutes.remove(0);
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
deleted file mode 100644
index 18ab566..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.http;
-
-import com.squareup.okhttp.internal.spdy.SpdyConnection;
-import com.squareup.okhttp.internal.spdy.SpdyStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import java.net.URL;
-import java.util.List;
-
-public final class SpdyTransport implements Transport {
- private final HttpEngine httpEngine;
- private final SpdyConnection spdyConnection;
- private SpdyStream stream;
-
- public SpdyTransport(HttpEngine httpEngine, SpdyConnection spdyConnection) {
- this.httpEngine = httpEngine;
- this.spdyConnection = spdyConnection;
- }
-
- @Override public OutputStream createRequestBody() throws IOException {
- // TODO: if we aren't streaming up to the server, we should buffer the whole request
- writeRequestHeaders();
- return stream.getOutputStream();
- }
-
- @Override public void writeRequestHeaders() throws IOException {
- if (stream != null) {
- return;
- }
- httpEngine.writingRequestHeaders();
- RawHeaders requestHeaders = httpEngine.requestHeaders.getHeaders();
- String version = httpEngine.connection.getHttpMinorVersion() == 1 ? "HTTP/1.1" : "HTTP/1.0";
- URL url = httpEngine.policy.getURL();
- requestHeaders.addSpdyRequestHeaders(httpEngine.method, HttpEngine.requestPath(url), version,
- HttpEngine.getOriginAddress(url), httpEngine.uri.getScheme());
- boolean hasRequestBody = httpEngine.hasRequestBody();
- boolean hasResponseBody = true;
- stream = spdyConnection.newStream(requestHeaders.toNameValueBlock(), hasRequestBody,
- hasResponseBody);
- stream.setReadTimeout(httpEngine.policy.getReadTimeout());
- }
-
- @Override public void writeRequestBody(RetryableOutputStream requestBody) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override public void flushRequest() throws IOException {
- stream.getOutputStream().close();
- }
-
- @Override public ResponseHeaders readResponseHeaders() throws IOException {
- List<String> nameValueBlock = stream.getResponseHeaders();
- RawHeaders rawHeaders = RawHeaders.fromNameValueBlock(nameValueBlock);
- rawHeaders.computeResponseStatusLineFromSpdyHeaders();
- httpEngine.receiveHeaders(rawHeaders);
- return new ResponseHeaders(httpEngine.uri, rawHeaders);
- }
-
- @Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException {
- return new UnknownLengthHttpInputStream(stream.getInputStream(), cacheRequest, httpEngine);
- }
-
- @Override public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
- InputStream responseBodyIn) {
- if (streamCancelled) {
- if (stream != null) {
- stream.closeLater(SpdyStream.RST_CANCEL);
- return true;
- } else {
- // If stream is null, it either means that writeRequestHeaders wasn't called
- // or that SpdyConnection#newStream threw an IOEXception. In both cases there's
- // nothing to do here and this stream can't be reused.
- return false;
- }
- }
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/Transport.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/Transport.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/Transport.java
deleted file mode 100644
index 518827e..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/Transport.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-
-interface Transport {
- /**
- * Returns an output stream where the request body can be written. The
- * returned stream will of one of two types:
- * <ul>
- * <li><strong>Direct.</strong> Bytes are written to the socket and
- * forgotten. This is most efficient, particularly for large request
- * bodies. The returned stream may be buffered; the caller must call
- * {@link #flushRequest} before reading the response.</li>
- * <li><strong>Buffered.</strong> Bytes are written to an in memory
- * buffer, and must be explicitly flushed with a call to {@link
- * #writeRequestBody}. This allows HTTP authorization (401, 407)
- * responses to be retransmitted transparently.</li>
- * </ul>
- */
- // TODO: don't bother retransmitting the request body? It's quite a corner
- // case and there's uncertainty whether Firefox or Chrome do this
- OutputStream createRequestBody() throws IOException;
-
- /** This should update the HTTP engine's sentRequestMillis field. */
- void writeRequestHeaders() throws IOException;
-
- /**
- * Sends the request body returned by {@link #createRequestBody} to the
- * remote peer.
- */
- void writeRequestBody(RetryableOutputStream requestBody) throws IOException;
-
- /** Flush the request body to the underlying socket. */
- void flushRequest() throws IOException;
-
- /** Read response headers and update the cookie manager. */
- ResponseHeaders readResponseHeaders() throws IOException;
-
- // TODO: make this the content stream?
- InputStream getTransferStream(CacheRequest cacheRequest) throws IOException;
-
- /** Returns true if the underlying connection can be recycled. */
- boolean makeReusable(boolean streamReusable, OutputStream requestBodyOut,
- InputStream responseBodyIn);
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
deleted file mode 100644
index 729e0b9..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.okhttp.internal.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-
-import static com.squareup.okhttp.internal.Util.checkOffsetAndCount;
-
-/** An HTTP message body terminated by the end of the underlying stream. */
-final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
- private boolean inputExhausted;
-
- UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest, HttpEngine httpEngine)
- throws IOException {
- super(is, httpEngine, cacheRequest);
- }
-
- @Override public int read(byte[] buffer, int offset, int count) throws IOException {
- checkOffsetAndCount(buffer.length, offset, count);
- checkNotClosed();
- if (in == null || inputExhausted) {
- return -1;
- }
- int read = in.read(buffer, offset, count);
- if (read == -1) {
- inputExhausted = true;
- endOfInput(false);
- return -1;
- }
- cacheWrite(buffer, offset, read);
- return read;
- }
-
- @Override public int available() throws IOException {
- checkNotClosed();
- return in == null ? 0 : in.available();
- }
-
- @Override public void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- if (!inputExhausted) {
- unexpectedEndOfInput();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
deleted file mode 100644
index 875fff0..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.spdy;
-
-import java.io.IOException;
-
-/** Listener to be notified when a connected peer creates a new stream. */
-public interface IncomingStreamHandler {
- IncomingStreamHandler REFUSE_INCOMING_STREAMS = new IncomingStreamHandler() {
- @Override public void receive(SpdyStream stream) throws IOException {
- stream.close(SpdyStream.RST_REFUSED_STREAM);
- }
- };
-
- /**
- * Handle a new stream from this connection's peer. Implementations should
- * respond by either {@link SpdyStream#reply replying to the stream} or
- * {@link SpdyStream#close closing it}. This response does not need to be
- * synchronous.
- */
- void receive(SpdyStream stream) throws IOException;
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Ping.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Ping.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Ping.java
deleted file mode 100644
index c585255..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Ping.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 Square, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.okhttp.internal.spdy;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A locally-originated ping.
- */
-public final class Ping {
- private final CountDownLatch latch = new CountDownLatch(1);
- private long sent = -1;
- private long received = -1;
-
- Ping() {
- }
-
- void send() {
- if (sent != -1) throw new IllegalStateException();
- sent = System.nanoTime();
- }
-
- void receive() {
- if (received != -1 || sent == -1) throw new IllegalStateException();
- received = System.nanoTime();
- latch.countDown();
- }
-
- void cancel() {
- if (received != -1 || sent == -1) throw new IllegalStateException();
- received = sent - 1;
- latch.countDown();
- }
-
- /**
- * Returns the round trip time for this ping in nanoseconds, waiting for the
- * response to arrive if necessary. Returns -1 if the response was
- * cancelled.
- */
- public long roundTripTime() throws InterruptedException {
- latch.await();
- return received - sent;
- }
-
- /**
- * Returns the round trip time for this ping in nanoseconds, or -1 if the
- * response was cancelled, or -2 if the timeout elapsed before the round
- * trip completed.
- */
- public long roundTripTime(long timeout, TimeUnit unit) throws InterruptedException {
- if (latch.await(timeout, unit)) {
- return received - sent;
- } else {
- return -2;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Settings.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Settings.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Settings.java
deleted file mode 100644
index 774d791..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/Settings.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2012 Square, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.okhttp.internal.spdy;
-
-final class Settings {
- /**
- * From the spdy/3 spec, the default initial window size for all streams is
- * 64 KiB. (Chrome 25 uses 10 MiB).
- */
- static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024;
-
- /** Peer request to clear durable settings. */
- static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1;
-
- /** Sent by servers only. The peer requests this setting persisted for future connections. */
- static final int PERSIST_VALUE = 0x1;
- /** Sent by clients only. The client is reminding the server of a persisted value. */
- static final int PERSISTED = 0x2;
-
- /** Sender's estimate of max incoming kbps. */
- static final int UPLOAD_BANDWIDTH = 0x1;
- /** Sender's estimate of max outgoing kbps. */
- static final int DOWNLOAD_BANDWIDTH = 0x2;
- /** Sender's estimate of milliseconds between sending a request and receiving a response. */
- static final int ROUND_TRIP_TIME = 0x3;
- /** Sender's maximum number of concurrent streams. */
- static final int MAX_CONCURRENT_STREAMS = 0x4;
- /** Current CWND in Packets. */
- static final int CURRENT_CWND = 0x5;
- /** Retransmission rate. Percentage */
- static final int DOWNLOAD_RETRANS_RATE = 0x6;
- /** Window size in bytes. */
- static final int INITIAL_WINDOW_SIZE = 0x7;
- /** Window size in bytes. */
- static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 0x8;
- /** Total number of settings. */
- static final int COUNT = 0x9;
-
- /** Bitfield of which flags that values. */
- private int set;
-
- /** Bitfield of flags that have {@link #PERSIST_VALUE}. */
- private int persistValue;
-
- /** Bitfield of flags that have {@link #PERSISTED}. */
- private int persisted;
-
- /** Flag values. */
- private final int[] values = new int[COUNT];
-
- void set(int id, int idFlags, int value) {
- if (id >= values.length) {
- return; // Discard unknown settings.
- }
-
- int bit = 1 << id;
- set |= bit;
- if ((idFlags & PERSIST_VALUE) != 0) {
- persistValue |= bit;
- } else {
- persistValue &= ~bit;
- }
- if ((idFlags & PERSISTED) != 0) {
- persisted |= bit;
- } else {
- persisted &= ~bit;
- }
-
- values[id] = value;
- }
-
- /** Returns true if a value has been assigned for the setting {@code id}. */
- boolean isSet(int id) {
- int bit = 1 << id;
- return (set & bit) != 0;
- }
-
- /** Returns the value for the setting {@code id}, or 0 if unset. */
- int get(int id) {
- return values[id];
- }
-
- /** Returns the flags for the setting {@code id}, or 0 if unset. */
- int flags(int id) {
- int result = 0;
- if (isPersisted(id)) result |= Settings.PERSISTED;
- if (persistValue(id)) result |= Settings.PERSIST_VALUE;
- return result;
- }
-
- /** Returns the number of settings that have values assigned. */
- int size() {
- return Integer.bitCount(set);
- }
-
- int getUploadBandwidth(int defaultValue) {
- int bit = 1 << UPLOAD_BANDWIDTH;
- return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue;
- }
-
- int getDownloadBandwidth(int defaultValue) {
- int bit = 1 << DOWNLOAD_BANDWIDTH;
- return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue;
- }
-
- int getRoundTripTime(int defaultValue) {
- int bit = 1 << ROUND_TRIP_TIME;
- return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue;
- }
-
- int getMaxConcurrentStreams(int defaultValue) {
- int bit = 1 << MAX_CONCURRENT_STREAMS;
- return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue;
- }
-
- int getCurrentCwnd(int defaultValue) {
- int bit = 1 << CURRENT_CWND;
- return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue;
- }
-
- int getDownloadRetransRate(int defaultValue) {
- int bit = 1 << DOWNLOAD_RETRANS_RATE;
- return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue;
- }
-
- int getInitialWindowSize(int defaultValue) {
- int bit = 1 << INITIAL_WINDOW_SIZE;
- return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue;
- }
-
- int getClientCertificateVectorSize(int defaultValue) {
- int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE;
- return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue;
- }
-
- /**
- * Returns true if this user agent should use this setting in future SPDY
- * connections to the same host.
- */
- boolean persistValue(int id) {
- int bit = 1 << id;
- return (persistValue & bit) != 0;
- }
-
- /** Returns true if this setting was persisted. */
- boolean isPersisted(int id) {
- int bit = 1 << id;
- return (persisted & bit) != 0;
- }
-
- /**
- * Writes {@code other} into this. If any setting is populated by this and
- * {@code other}, the value and flags from {@code other} will be kept.
- */
- void merge(Settings other) {
- for (int i = 0; i < COUNT; i++) {
- if (!other.isSet(i)) continue;
- set(i, other.flags(i), other.get(i));
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java
deleted file mode 100644
index fccd14f..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.spdy;
-
-import com.squareup.okhttp.internal.NamedRunnable;
-import com.squareup.okhttp.internal.Util;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import static java.util.concurrent.Executors.defaultThreadFactory;
-
-/**
- * A socket connection to a remote peer. A connection hosts streams which can
- * send and receive data.
- *
- * <p>Many methods in this API are <strong>synchronous:</strong> the call is
- * completed before the method returns. This is typical for Java but atypical
- * for SPDY. This is motivated by exception transparency: an IOException that
- * was triggered by a certain caller can be caught and handled by that caller.
- */
-public final class SpdyConnection implements Closeable {
-
- // Internal state of this connection is guarded by 'this'. No blocking
- // operations may be performed while holding this lock!
- //
- // Socket writes are guarded by spdyWriter.
- //
- // Socket reads are unguarded but are only made by the reader thread.
- //
- // Certain operations (like SYN_STREAM) need to synchronize on both the
- // spdyWriter (to do blocking I/O) and this (to create streams). Such
- // operations must synchronize on 'this' last. This ensures that we never
- // wait for a blocking operation while holding 'this'.
-
- static final int FLAG_FIN = 0x1;
- static final int FLAG_UNIDIRECTIONAL = 0x2;
-
- static final int TYPE_DATA = 0x0;
- static final int TYPE_SYN_STREAM = 0x1;
- static final int TYPE_SYN_REPLY = 0x2;
- static final int TYPE_RST_STREAM = 0x3;
- static final int TYPE_SETTINGS = 0x4;
- static final int TYPE_NOOP = 0x5;
- static final int TYPE_PING = 0x6;
- static final int TYPE_GOAWAY = 0x7;
- static final int TYPE_HEADERS = 0x8;
- static final int TYPE_WINDOW_UPDATE = 0x9;
- static final int TYPE_CREDENTIAL = 0x10;
- static final int VERSION = 3;
-
- static final int GOAWAY_OK = 0;
- static final int GOAWAY_PROTOCOL_ERROR = 1;
- static final int GOAWAY_INTERNAL_ERROR = 2;
-
- private static final ExecutorService executor =
- new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>(), defaultThreadFactory());
-
- /** True if this peer initiated the connection. */
- final boolean client;
-
- /**
- * User code to run in response to an incoming stream. Callbacks must not be
- * run on the callback executor.
- */
- private final IncomingStreamHandler handler;
- private final SpdyReader spdyReader;
- private final SpdyWriter spdyWriter;
-
- private final Map<Integer, SpdyStream> streams = new HashMap<Integer, SpdyStream>();
- private final String hostName;
- private int lastGoodStreamId;
- private int nextStreamId;
- private boolean shutdown;
- private long idleStartTimeNs = System.nanoTime();
-
- /** Lazily-created map of in-flight pings awaiting a response. Guarded by this. */
- private Map<Integer, Ping> pings;
- private int nextPingId;
-
- /** Lazily-created settings for this connection. */
- Settings settings;
-
- private SpdyConnection(Builder builder) {
- client = builder.client;
- handler = builder.handler;
- spdyReader = new SpdyReader(builder.in);
- spdyWriter = new SpdyWriter(builder.out);
- nextStreamId = builder.client ? 1 : 2;
- nextPingId = builder.client ? 1 : 2;
-
- hostName = builder.hostName;
-
- new Thread(new Reader(), "Spdy Reader " + hostName).start();
- }
-
- /**
- * Returns the number of {@link SpdyStream#isOpen() open streams} on this
- * connection.
- */
- public synchronized int openStreamCount() {
- return streams.size();
- }
-
- private synchronized SpdyStream getStream(int id) {
- return streams.get(id);
- }
-
- synchronized SpdyStream removeStream(int streamId) {
- SpdyStream stream = streams.remove(streamId);
- if (stream != null && streams.isEmpty()) {
- setIdle(true);
- }
- return stream;
- }
-
- private synchronized void setIdle(boolean value) {
- idleStartTimeNs = value ? System.nanoTime() : 0L;
- }
-
- /** Returns true if this connection is idle. */
- public synchronized boolean isIdle() {
- return idleStartTimeNs != 0L;
- }
-
- /** Returns the time in ns when this connection became idle or 0L if connection is not idle. */
- public synchronized long getIdleStartTimeNs() {
- return idleStartTimeNs;
- }
-
- /**
- * Returns a new locally-initiated stream.
- *
- * @param out true to create an output stream that we can use to send data
- * to the remote peer. Corresponds to {@code FLAG_FIN}.
- * @param in true to create an input stream that the remote peer can use to
- * send data to us. Corresponds to {@code FLAG_UNIDIRECTIONAL}.
- */
- public SpdyStream newStream(List<String> requestHeaders, boolean out, boolean in)
- throws IOException {
- int flags = (out ? 0 : FLAG_FIN) | (in ? 0 : FLAG_UNIDIRECTIONAL);
- int associatedStreamId = 0; // TODO: permit the caller to specify an associated stream?
- int priority = 0; // TODO: permit the caller to specify a priority?
- int slot = 0; // TODO: permit the caller to specify a slot?
- SpdyStream stream;
- int streamId;
-
- synchronized (spdyWriter) {
- synchronized (this) {
- if (shutdown) {
- throw new IOException("shutdown");
- }
- streamId = nextStreamId;
- nextStreamId += 2;
- stream = new SpdyStream(streamId, this, flags, priority, slot, requestHeaders, settings);
- if (stream.isOpen()) {
- streams.put(streamId, stream);
- setIdle(false);
- }
- }
-
- spdyWriter.synStream(flags, streamId, associatedStreamId, priority, slot, requestHeaders);
- }
-
- return stream;
- }
-
- void writeSynReply(int streamId, int flags, List<String> alternating) throws IOException {
- spdyWriter.synReply(flags, streamId, alternating);
- }
-
- /** Writes a complete data frame. */
- void writeFrame(byte[] bytes, int offset, int length) throws IOException {
- synchronized (spdyWriter) {
- spdyWriter.out.write(bytes, offset, length);
- }
- }
-
- void writeSynResetLater(final int streamId, final int statusCode) {
- executor.submit(
- new NamedRunnable(String.format("Spdy Writer %s stream %d", hostName, streamId)) {
- @Override public void execute() {
- try {
- writeSynReset(streamId, statusCode);
- } catch (IOException ignored) {
- }
- }
- });
- }
-
- void writeSynReset(int streamId, int statusCode) throws IOException {
- spdyWriter.rstStream(streamId, statusCode);
- }
-
- void writeWindowUpdateLater(final int streamId, final int deltaWindowSize) {
- executor.submit(
- new NamedRunnable(String.format("Spdy Writer %s stream %d", hostName, streamId)) {
- @Override public void execute() {
- try {
- writeWindowUpdate(streamId, deltaWindowSize);
- } catch (IOException ignored) {
- }
- }
- });
- }
-
- void writeWindowUpdate(int streamId, int deltaWindowSize) throws IOException {
- spdyWriter.windowUpdate(streamId, deltaWindowSize);
- }
-
- /**
- * Sends a ping frame to the peer. Use the returned object to await the
- * ping's response and observe its round trip time.
- */
- public Ping ping() throws IOException {
- Ping ping = new Ping();
- int pingId;
- synchronized (this) {
- if (shutdown) {
- throw new IOException("shutdown");
- }
- pingId = nextPingId;
- nextPingId += 2;
- if (pings == null) pings = new HashMap<Integer, Ping>();
- pings.put(pingId, ping);
- }
- writePing(pingId, ping);
- return ping;
- }
-
- private void writePingLater(final int streamId, final Ping ping) {
- executor.submit(new NamedRunnable(String.format("Spdy Writer %s ping %d", hostName, streamId)) {
- @Override public void execute() {
- try {
- writePing(streamId, ping);
- } catch (IOException ignored) {
- }
- }
- });
- }
-
- private void writePing(int id, Ping ping) throws IOException {
- synchronized (spdyWriter) {
- // Observe the sent time immediately before performing I/O.
- if (ping != null) ping.send();
- spdyWriter.ping(0, id);
- }
- }
-
- private synchronized Ping removePing(int id) {
- return pings != null ? pings.remove(id) : null;
- }
-
- /** Sends a noop frame to the peer. */
- public void noop() throws IOException {
- spdyWriter.noop();
- }
-
- public void flush() throws IOException {
- synchronized (spdyWriter) {
- spdyWriter.out.flush();
- }
- }
-
- /**
- * Degrades this connection such that new streams can neither be created
- * locally, nor accepted from the remote peer. Existing streams are not
- * impacted. This is intended to permit an endpoint to gracefully stop
- * accepting new requests without harming previously established streams.
- *
- * @param statusCode one of {@link #GOAWAY_OK}, {@link
- * #GOAWAY_INTERNAL_ERROR} or {@link #GOAWAY_PROTOCOL_ERROR}.
- */
- public void shutdown(int statusCode) throws IOException {
- synchronized (spdyWriter) {
- int lastGoodStreamId;
- synchronized (this) {
- if (shutdown) {
- return;
- }
- shutdown = true;
- lastGoodStreamId = this.lastGoodStreamId;
- }
- spdyWriter.goAway(0, lastGoodStreamId, statusCode);
- }
- }
-
- /**
- * Closes this connection. This cancels all open streams and unanswered
- * pings. It closes the underlying input and output streams and shuts down
- * internal executor services.
- */
- @Override public void close() throws IOException {
- close(GOAWAY_OK, SpdyStream.RST_CANCEL);
- }
-
- private void close(int shutdownStatusCode, int rstStatusCode) throws IOException {
- assert (!Thread.holdsLock(this));
- IOException thrown = null;
- try {
- shutdown(shutdownStatusCode);
- } catch (IOException e) {
- thrown = e;
- }
-
- SpdyStream[] streamsToClose = null;
- Ping[] pingsToCancel = null;
- synchronized (this) {
- if (!streams.isEmpty()) {
- streamsToClose = streams.values().toArray(new SpdyStream[streams.size()]);
- streams.clear();
- setIdle(false);
- }
- if (pings != null) {
- pingsToCancel = pings.values().toArray(new Ping[pings.size()]);
- pings = null;
- }
- }
-
- if (streamsToClose != null) {
- for (SpdyStream stream : streamsToClose) {
- try {
- stream.close(rstStatusCode);
- } catch (IOException e) {
- if (thrown != null) thrown = e;
- }
- }
- }
-
- if (pingsToCancel != null) {
- for (Ping ping : pingsToCancel) {
- ping.cancel();
- }
- }
-
- try {
- spdyReader.close();
- } catch (IOException e) {
- thrown = e;
- }
- try {
- spdyWriter.close();
- } catch (IOException e) {
- if (thrown == null) thrown = e;
- }
-
- if (thrown != null) throw thrown;
- }
-
- public static class Builder {
- private String hostName;
- private InputStream in;
- private OutputStream out;
- private IncomingStreamHandler handler = IncomingStreamHandler.REFUSE_INCOMING_STREAMS;
- public boolean client;
-
- public Builder(boolean client, Socket socket) throws IOException {
- this("", client, socket.getInputStream(), socket.getOutputStream());
- }
-
- public Builder(boolean client, InputStream in, OutputStream out) {
- this("", client, in, out);
- }
-
- /**
- * @param client true if this peer initiated the connection; false if
- * this peer accepted the connection.
- */
- public Builder(String hostName, boolean client, Socket socket) throws IOException {
- this(hostName, client, socket.getInputStream(), socket.getOutputStream());
- }
-
- /**
- * @param client true if this peer initiated the connection; false if this
- * peer accepted the connection.
- */
- public Builder(String hostName, boolean client, InputStream in, OutputStream out) {
- this.hostName = hostName;
- this.client = client;
- this.in = in;
- this.out = out;
- }
-
- public Builder handler(IncomingStreamHandler handler) {
- this.handler = handler;
- return this;
- }
-
- public SpdyConnection build() {
- return new SpdyConnection(this);
- }
- }
-
- private class Reader implements Runnable, SpdyReader.Handler {
- @Override public void run() {
- int shutdownStatusCode = GOAWAY_INTERNAL_ERROR;
- int rstStatusCode = SpdyStream.RST_INTERNAL_ERROR;
- try {
- while (spdyReader.nextFrame(this)) {
- }
- shutdownStatusCode = GOAWAY_OK;
- rstStatusCode = SpdyStream.RST_CANCEL;
- } catch (IOException e) {
- shutdownStatusCode = GOAWAY_PROTOCOL_ERROR;
- rstStatusCode = SpdyStream.RST_PROTOCOL_ERROR;
- } finally {
- try {
- close(shutdownStatusCode, rstStatusCode);
- } catch (IOException ignored) {
- }
- }
- }
-
- @Override public void data(int flags, int streamId, InputStream in, int length)
- throws IOException {
- SpdyStream dataStream = getStream(streamId);
- if (dataStream == null) {
- writeSynResetLater(streamId, SpdyStream.RST_INVALID_STREAM);
- Util.skipByReading(in, length);
- return;
- }
- dataStream.receiveData(in, length);
- if ((flags & SpdyConnection.FLAG_FIN) != 0) {
- dataStream.receiveFin();
- }
- }
-
- @Override
- public void synStream(int flags, int streamId, int associatedStreamId, int priority, int slot,
- List<String> nameValueBlock) {
- final SpdyStream synStream;
- final SpdyStream previous;
- synchronized (SpdyConnection.this) {
- synStream =
- new SpdyStream(streamId, SpdyConnection.this, flags, priority, slot, nameValueBlock,
- settings);
- if (shutdown) {
- return;
- }
- lastGoodStreamId = streamId;
- previous = streams.put(streamId, synStream);
- }
- if (previous != null) {
- previous.closeLater(SpdyStream.RST_PROTOCOL_ERROR);
- removeStream(streamId);
- return;
- }
-
- executor.submit(
- new NamedRunnable(String.format("Callback %s stream %d", hostName, streamId)) {
- @Override public void execute() {
- try {
- handler.receive(synStream);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- });
- }
-
- @Override public void synReply(int flags, int streamId, List<String> nameValueBlock)
- throws IOException {
- SpdyStream replyStream = getStream(streamId);
- if (replyStream == null) {
- writeSynResetLater(streamId, SpdyStream.RST_INVALID_STREAM);
- return;
- }
- replyStream.receiveReply(nameValueBlock);
- if ((flags & SpdyConnection.FLAG_FIN) != 0) {
- replyStream.receiveFin();
- }
- }
-
- @Override public void headers(int flags, int streamId, List<String> nameValueBlock)
- throws IOException {
- SpdyStream replyStream = getStream(streamId);
- if (replyStream != null) {
- replyStream.receiveHeaders(nameValueBlock);
- }
- }
-
- @Override public void rstStream(int flags, int streamId, int statusCode) {
- SpdyStream rstStream = removeStream(streamId);
- if (rstStream != null) {
- rstStream.receiveRstStream(statusCode);
- }
- }
-
- @Override public void settings(int flags, Settings newSettings) {
- SpdyStream[] streamsToNotify = null;
- synchronized (SpdyConnection.this) {
- if (settings == null || (flags & Settings.FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) != 0) {
- settings = newSettings;
- } else {
- settings.merge(newSettings);
- }
- if (!streams.isEmpty()) {
- streamsToNotify = streams.values().toArray(new SpdyStream[streams.size()]);
- }
- }
- if (streamsToNotify != null) {
- for (SpdyStream stream : streamsToNotify) {
- // The synchronization here is ugly. We need to synchronize on 'this' to guard
- // reads to 'settings'. We synchronize on 'stream' to guard the state change.
- // And we need to acquire the 'stream' lock first, since that may block.
- synchronized (stream) {
- synchronized (this) {
- stream.receiveSettings(settings);
- }
- }
- }
- }
- }
-
- @Override public void noop() {
- }
-
- @Override public void ping(int flags, int streamId) {
- if (client != (streamId % 2 == 1)) {
- // Respond to a client ping if this is a server and vice versa.
- writePingLater(streamId, null);
- } else {
- Ping ping = removePing(streamId);
- if (ping != null) {
- ping.receive();
- }
- }
- }
-
- @Override public void goAway(int flags, int lastGoodStreamId, int statusCode) {
- synchronized (SpdyConnection.this) {
- shutdown = true;
-
- // Fail all streams created after the last good stream ID.
- for (Iterator<Map.Entry<Integer, SpdyStream>> i = streams.entrySet().iterator();
- i.hasNext(); ) {
- Map.Entry<Integer, SpdyStream> entry = i.next();
- int streamId = entry.getKey();
- if (streamId > lastGoodStreamId && entry.getValue().isLocallyInitiated()) {
- entry.getValue().receiveRstStream(SpdyStream.RST_REFUSED_STREAM);
- i.remove();
- }
- }
- }
- }
-
- @Override public void windowUpdate(int flags, int streamId, int deltaWindowSize) {
- SpdyStream stream = getStream(streamId);
- if (stream != null) {
- stream.receiveWindowUpdate(deltaWindowSize);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyReader.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyReader.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyReader.java
deleted file mode 100644
index 7d3f2bd..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyReader.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.spdy;
-
-import com.squareup.okhttp.internal.Util;
-import java.io.Closeable;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.ProtocolException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterInputStream;
-
-/** Read spdy/3 frames. */
-final class SpdyReader implements Closeable {
- static final byte[] DICTIONARY;
- static {
- try {
- DICTIONARY = ("\u0000\u0000\u0000\u0007options\u0000\u0000\u0000\u0004hea"
- + "d\u0000\u0000\u0000\u0004post\u0000\u0000\u0000\u0003put\u0000\u0000\u0000\u0006dele"
- + "te\u0000\u0000\u0000\u0005trace\u0000\u0000\u0000\u0006accept\u0000\u0000\u0000"
- + "\u000Eaccept-charset\u0000\u0000\u0000\u000Faccept-encoding\u0000\u0000\u0000\u000Fa"
- + "ccept-language\u0000\u0000\u0000\raccept-ranges\u0000\u0000\u0000\u0003age\u0000"
- + "\u0000\u0000\u0005allow\u0000\u0000\u0000\rauthorization\u0000\u0000\u0000\rcache-co"
- + "ntrol\u0000\u0000\u0000\nconnection\u0000\u0000\u0000\fcontent-base\u0000\u0000"
- + "\u0000\u0010content-encoding\u0000\u0000\u0000\u0010content-language\u0000\u0000"
- + "\u0000\u000Econtent-length\u0000\u0000\u0000\u0010content-location\u0000\u0000\u0000"
- + "\u000Bcontent-md5\u0000\u0000\u0000\rcontent-range\u0000\u0000\u0000\fcontent-type"
- + "\u0000\u0000\u0000\u0004date\u0000\u0000\u0000\u0004etag\u0000\u0000\u0000\u0006expe"
- + "ct\u0000\u0000\u0000\u0007expires\u0000\u0000\u0000\u0004from\u0000\u0000\u0000"
- + "\u0004host\u0000\u0000\u0000\bif-match\u0000\u0000\u0000\u0011if-modified-since"
- + "\u0000\u0000\u0000\rif-none-match\u0000\u0000\u0000\bif-range\u0000\u0000\u0000"
- + "\u0013if-unmodified-since\u0000\u0000\u0000\rlast-modified\u0000\u0000\u0000\blocati"
- + "on\u0000\u0000\u0000\fmax-forwards\u0000\u0000\u0000\u0006pragma\u0000\u0000\u0000"
- + "\u0012proxy-authenticate\u0000\u0000\u0000\u0013proxy-authorization\u0000\u0000"
- + "\u0000\u0005range\u0000\u0000\u0000\u0007referer\u0000\u0000\u0000\u000Bretry-after"
- + "\u0000\u0000\u0000\u0006server\u0000\u0000\u0000\u0002te\u0000\u0000\u0000\u0007trai"
- + "ler\u0000\u0000\u0000\u0011transfer-encoding\u0000\u0000\u0000\u0007upgrade\u0000"
- + "\u0000\u0000\nuser-agent\u0000\u0000\u0000\u0004vary\u0000\u0000\u0000\u0003via"
- + "\u0000\u0000\u0000\u0007warning\u0000\u0000\u0000\u0010www-authenticate\u0000\u0000"
- + "\u0000\u0006method\u0000\u0000\u0000\u0003get\u0000\u0000\u0000\u0006status\u0000"
- + "\u0000\u0000\u0006200 OK\u0000\u0000\u0000\u0007version\u0000\u0000\u0000\bHTTP/1.1"
- + "\u0000\u0000\u0000\u0003url\u0000\u0000\u0000\u0006public\u0000\u0000\u0000\nset-coo"
- + "kie\u0000\u0000\u0000\nkeep-alive\u0000\u0000\u0000\u0006origin100101201202205206300"
- + "302303304305306307402405406407408409410411412413414415416417502504505203 Non-Authori"
- + "tative Information204 No Content301 Moved Permanently400 Bad Request401 Unauthorized"
- + "403 Forbidden404 Not Found500 Internal Server Error501 Not Implemented503 Service Un"
- + "availableJan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec 00:00:00 Mon, Tue, Wed, Th"
- + "u, Fri, Sat, Sun, GMTchunked,text/html,image/png,image/jpg,image/gif,application/xml"
- + ",application/xhtml+xml,text/plain,text/javascript,publicprivatemax-age=gzip,deflate,"
- + "sdchcharset=utf-8charset=iso-8859-1,utf-,*,enq=0.").getBytes(Util.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
- }
-
- private final DataInputStream in;
- private final DataInputStream nameValueBlockIn;
- private int compressedLimit;
-
- SpdyReader(InputStream in) {
- this.in = new DataInputStream(in);
- this.nameValueBlockIn = newNameValueBlockStream();
- }
-
- /**
- * Send the next frame to {@code handler}. Returns true unless there are no
- * more frames on the stream.
- */
- public boolean nextFrame(Handler handler) throws IOException {
- int w1;
- try {
- w1 = in.readInt();
- } catch (IOException e) {
- return false; // This might be a normal socket close.
- }
- int w2 = in.readInt();
-
- boolean control = (w1 & 0x80000000) != 0;
- int flags = (w2 & 0xff000000) >>> 24;
- int length = (w2 & 0xffffff);
-
- if (control) {
- int version = (w1 & 0x7fff0000) >>> 16;
- int type = (w1 & 0xffff);
-
- if (version != 3) {
- throw new ProtocolException("version != 3: " + version);
- }
-
- switch (type) {
- case SpdyConnection.TYPE_SYN_STREAM:
- readSynStream(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_SYN_REPLY:
- readSynReply(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_RST_STREAM:
- readRstStream(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_SETTINGS:
- readSettings(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_NOOP:
- if (length != 0) throw ioException("TYPE_NOOP length: %d != 0", length);
- handler.noop();
- return true;
-
- case SpdyConnection.TYPE_PING:
- readPing(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_GOAWAY:
- readGoAway(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_HEADERS:
- readHeaders(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_WINDOW_UPDATE:
- readWindowUpdate(handler, flags, length);
- return true;
-
- case SpdyConnection.TYPE_CREDENTIAL:
- Util.skipByReading(in, length);
- throw new UnsupportedOperationException("TODO"); // TODO: implement
-
- default:
- throw new IOException("Unexpected frame");
- }
- } else {
- int streamId = w1 & 0x7fffffff;
- handler.data(flags, streamId, in, length);
- return true;
- }
- }
-
- private void readSynStream(Handler handler, int flags, int length) throws IOException {
- int w1 = in.readInt();
- int w2 = in.readInt();
- int s3 = in.readShort();
- int streamId = w1 & 0x7fffffff;
- int associatedStreamId = w2 & 0x7fffffff;
- int priority = (s3 & 0xe000) >>> 13;
- int slot = s3 & 0xff;
- List<String> nameValueBlock = readNameValueBlock(length - 10);
- handler.synStream(flags, streamId, associatedStreamId, priority, slot, nameValueBlock);
- }
-
- private void readSynReply(Handler handler, int flags, int length) throws IOException {
- int w1 = in.readInt();
- int streamId = w1 & 0x7fffffff;
- List<String> nameValueBlock = readNameValueBlock(length - 4);
- handler.synReply(flags, streamId, nameValueBlock);
- }
-
- private void readRstStream(Handler handler, int flags, int length) throws IOException {
- if (length != 8) throw ioException("TYPE_RST_STREAM length: %d != 8", length);
- int streamId = in.readInt() & 0x7fffffff;
- int statusCode = in.readInt();
- handler.rstStream(flags, streamId, statusCode);
- }
-
- private void readHeaders(Handler handler, int flags, int length) throws IOException {
- int w1 = in.readInt();
- int streamId = w1 & 0x7fffffff;
- List<String> nameValueBlock = readNameValueBlock(length - 4);
- handler.headers(flags, streamId, nameValueBlock);
- }
-
- private void readWindowUpdate(Handler handler, int flags, int length) throws IOException {
- if (length != 8) throw ioException("TYPE_WINDOW_UPDATE length: %d != 8", length);
- int w1 = in.readInt();
- int w2 = in.readInt();
- int streamId = w1 & 0x7fffffff;
- int deltaWindowSize = w2 & 0x7fffffff;
- handler.windowUpdate(flags, streamId, deltaWindowSize);
- }
-
- private DataInputStream newNameValueBlockStream() {
- // Limit the inflater input stream to only those bytes in the Name/Value block.
- final InputStream throttleStream = new InputStream() {
- @Override public int read() throws IOException {
- return Util.readSingleByte(this);
- }
-
- @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException {
- byteCount = Math.min(byteCount, compressedLimit);
- int consumed = in.read(buffer, offset, byteCount);
- compressedLimit -= consumed;
- return consumed;
- }
-
- @Override public void close() throws IOException {
- in.close();
- }
- };
-
- // Subclass inflater to install a dictionary when it's needed.
- Inflater inflater = new Inflater() {
- @Override
- public int inflate(byte[] buffer, int offset, int count) throws DataFormatException {
- int result = super.inflate(buffer, offset, count);
- if (result == 0 && needsDictionary()) {
- setDictionary(DICTIONARY);
- result = super.inflate(buffer, offset, count);
- }
- return result;
- }
- };
-
- return new DataInputStream(new InflaterInputStream(throttleStream, inflater));
- }
-
- private List<String> readNameValueBlock(int length) throws IOException {
- this.compressedLimit += length;
- try {
- int numberOfPairs = nameValueBlockIn.readInt();
- if (numberOfPairs < 0) {
- Logger.getLogger(getClass().getName()).warning("numberOfPairs < 0: " + numberOfPairs);
- throw ioException("numberOfPairs < 0");
- }
- List<String> entries = new ArrayList<String>(numberOfPairs * 2);
- for (int i = 0; i < numberOfPairs; i++) {
- String name = readString();
- String values = readString();
- if (name.length() == 0) throw ioException("name.length == 0");
- if (values.length() == 0) throw ioException("values.length == 0");
- entries.add(name);
- entries.add(values);
- }
-
- if (compressedLimit != 0) {
- Logger.getLogger(getClass().getName()).warning("compressedLimit > 0: " + compressedLimit);
- }
-
- return entries;
- } catch (DataFormatException e) {
- throw new IOException(e.getMessage());
- }
- }
-
- private String readString() throws DataFormatException, IOException {
- int length = nameValueBlockIn.readInt();
- byte[] bytes = new byte[length];
- Util.readFully(nameValueBlockIn, bytes);
- return new String(bytes, 0, length, "UTF-8");
- }
-
- private void readPing(Handler handler, int flags, int length) throws IOException {
- if (length != 4) throw ioException("TYPE_PING length: %d != 4", length);
- int id = in.readInt();
- handler.ping(flags, id);
- }
-
- private void readGoAway(Handler handler, int flags, int length) throws IOException {
- if (length != 8) throw ioException("TYPE_GOAWAY length: %d != 8", length);
- int lastGoodStreamId = in.readInt() & 0x7fffffff;
- int statusCode = in.readInt();
- handler.goAway(flags, lastGoodStreamId, statusCode);
- }
-
- private void readSettings(Handler handler, int flags, int length) throws IOException {
- int numberOfEntries = in.readInt();
- if (length != 4 + 8 * numberOfEntries) {
- throw ioException("TYPE_SETTINGS length: %d != 4 + 8 * %d", length, numberOfEntries);
- }
- Settings settings = new Settings();
- for (int i = 0; i < numberOfEntries; i++) {
- int w1 = in.readInt();
- int value = in.readInt();
- int idFlags = (w1 & 0xff000000) >>> 24;
- int id = w1 & 0xffffff;
- settings.set(id, idFlags, value);
- }
- handler.settings(flags, settings);
- }
-
- private static IOException ioException(String message, Object... args) throws IOException {
- throw new IOException(String.format(message, args));
- }
-
- @Override public void close() throws IOException {
- Util.closeAll(in, nameValueBlockIn);
- }
-
- public interface Handler {
- void data(int flags, int streamId, InputStream in, int length) throws IOException;
-
- void synStream(int flags, int streamId, int associatedStreamId, int priority, int slot,
- List<String> nameValueBlock);
-
- void synReply(int flags, int streamId, List<String> nameValueBlock) throws IOException;
- void headers(int flags, int streamId, List<String> nameValueBlock) throws IOException;
- void rstStream(int flags, int streamId, int statusCode);
- void settings(int flags, Settings settings);
- void noop();
- void ping(int flags, int streamId);
- void goAway(int flags, int lastGoodStreamId, int statusCode);
- void windowUpdate(int flags, int streamId, int deltaWindowSize);
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/91c74886/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java b/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java
deleted file mode 100644
index 744a04e..0000000
--- a/lib/cordova-android/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.squareup.okhttp.internal.spdy;
-
-import com.squareup.okhttp.internal.Util;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.squareup.okhttp.internal.Util.checkOffsetAndCount;
-import static com.squareup.okhttp.internal.Util.pokeInt;
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-/** A logical bidirectional stream. */
-public final class SpdyStream {
-
- // Internal state is guarded by this. No long-running or potentially
- // blocking operations are performed while the lock is held.
-
- private static final int DATA_FRAME_HEADER_LENGTH = 8;
-
- private static final String[] STATUS_CODE_NAMES = {
- null,
- "PROTOCOL_ERROR",
- "INVALID_STREAM",
- "REFUSED_STREAM",
- "UNSUPPORTED_VERSION",
- "CANCEL",
- "INTERNAL_ERROR",
- "FLOW_CONTROL_ERROR",
- "STREAM_IN_USE",
- "STREAM_ALREADY_CLOSED",
- "INVALID_CREDENTIALS",
- "FRAME_TOO_LARGE"
- };
-
- public static final int RST_PROTOCOL_ERROR = 1;
- public static final int RST_INVALID_STREAM = 2;
- public static final int RST_REFUSED_STREAM = 3;
- public static final int RST_UNSUPPORTED_VERSION = 4;
- public static final int RST_CANCEL = 5;
- public static final int RST_INTERNAL_ERROR = 6;
- public static final int RST_FLOW_CONTROL_ERROR = 7;
- public static final int RST_STREAM_IN_USE = 8;
- public static final int RST_STREAM_ALREADY_CLOSED = 9;
- public static final int RST_INVALID_CREDENTIALS = 10;
- public static final int RST_FRAME_TOO_LARGE = 11;
-
- /**
- * The number of unacknowledged bytes at which the input stream will send
- * the peer a {@code WINDOW_UPDATE} frame. Must be less than this client's
- * window size, otherwise the remote peer will stop sending data on this
- * stream. (Chrome 25 uses 5 MiB.)
- */
- public static final int WINDOW_UPDATE_THRESHOLD = Settings.DEFAULT_INITIAL_WINDOW_SIZE / 2;
-
- private final int id;
- private final SpdyConnection connection;
- private final int priority;
- private final int slot;
- private long readTimeoutMillis = 0;
- private int writeWindowSize;
-
- /** Headers sent by the stream initiator. Immutable and non null. */
- private final List<String> requestHeaders;
-
- /** Headers sent in the stream reply. Null if reply is either not sent or not sent yet. */
- private List<String> responseHeaders;
-
- private final SpdyDataInputStream in = new SpdyDataInputStream();
- private final SpdyDataOutputStream out = new SpdyDataOutputStream();
-
- /**
- * The reason why this stream was abnormally closed. If there are multiple
- * reasons to abnormally close this stream (such as both peers closing it
- * near-simultaneously) then this is the first reason known to this peer.
- */
- private int rstStatusCode = -1;
-
- SpdyStream(int id, SpdyConnection connection, int flags, int priority, int slot,
- List<String> requestHeaders, Settings settings) {
- if (connection == null) throw new NullPointerException("connection == null");
- if (requestHeaders == null) throw new NullPointerException("requestHeaders == null");
- this.id = id;
- this.connection = connection;
- this.priority = priority;
- this.slot = slot;
- this.requestHeaders = requestHeaders;
-
- if (isLocallyInitiated()) {
- // I am the sender
- in.finished = (flags & SpdyConnection.FLAG_UNIDIRECTIONAL) != 0;
- out.finished = (flags & SpdyConnection.FLAG_FIN) != 0;
- } else {
- // I am the receiver
- in.finished = (flags & SpdyConnection.FLAG_FIN) != 0;
- out.finished = (flags & SpdyConnection.FLAG_UNIDIRECTIONAL) != 0;
- }
-
- setSettings(settings);
- }
-
- /**
- * Returns true if this stream is open. A stream is open until either:
- * <ul>
- * <li>A {@code SYN_RESET} frame abnormally terminates the stream.
- * <li>Both input and output streams have transmitted all data and
- * headers.
- * </ul>
- * Note that the input stream may continue to yield data even after a stream
- * reports itself as not open. This is because input data is buffered.
- */
- public synchronized boolean isOpen() {
- if (rstStatusCode != -1) {
- return false;
- }
- if ((in.finished || in.closed) && (out.finished || out.closed) && responseHeaders != null) {
- return false;
- }
- return true;
- }
-
- /** Returns true if this stream was created by this peer. */
- public boolean isLocallyInitiated() {
- boolean streamIsClient = (id % 2 == 1);
- return connection.client == streamIsClient;
- }
-
- public SpdyConnection getConnection() {
- return connection;
- }
-
- public List<String> getRequestHeaders() {
- return requestHeaders;
- }
-
- /**
- * Returns the stream's response headers, blocking if necessary if they
- * have not been received yet.
- */
- public synchronized List<String> getResponseHeaders() throws IOException {
- try {
- while (responseHeaders == null && rstStatusCode == -1) {
- wait();
- }
- if (responseHeaders != null) {
- return responseHeaders;
- }
- throw new IOException("stream was reset: " + rstStatusString());
- } catch (InterruptedException e) {
- InterruptedIOException rethrow = new InterruptedIOException();
- rethrow.initCause(e);
- throw rethrow;
- }
- }
-
- /**
- * Returns the reason why this stream was closed, or -1 if it closed
- * normally or has not yet been closed. Valid reasons are {@link
- * #RST_PROTOCOL_ERROR}, {@link #RST_INVALID_STREAM}, {@link
- * #RST_REFUSED_STREAM}, {@link #RST_UNSUPPORTED_VERSION}, {@link
- * #RST_CANCEL}, {@link #RST_INTERNAL_ERROR} and {@link
- * #RST_FLOW_CONTROL_ERROR}.
- */
- public synchronized int getRstStatusCode() {
- return rstStatusCode;
- }
-
- /**
- * Sends a reply to an incoming stream.
- *
- * @param out true to create an output stream that we can use to send data
- * to the remote peer. Corresponds to {@code FLAG_FIN}.
- */
- public void reply(List<String> responseHeaders, boolean out) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- int flags = 0;
- synchronized (this) {
- if (responseHeaders == null) {
- throw new NullPointerException("responseHeaders == null");
- }
- if (isLocallyInitiated()) {
- throw new IllegalStateException("cannot reply to a locally initiated stream");
- }
- if (this.responseHeaders != null) {
- throw new IllegalStateException("reply already sent");
- }
- this.responseHeaders = responseHeaders;
- if (!out) {
- this.out.finished = true;
- flags |= SpdyConnection.FLAG_FIN;
- }
- }
- connection.writeSynReply(id, flags, responseHeaders);
- }
-
- /**
- * Sets the maximum time to wait on input stream reads before failing with a
- * {@code SocketTimeoutException}, or {@code 0} to wait indefinitely.
- */
- public void setReadTimeout(long readTimeoutMillis) {
- this.readTimeoutMillis = readTimeoutMillis;
- }
-
- public long getReadTimeoutMillis() {
- return readTimeoutMillis;
- }
-
- /** Returns an input stream that can be used to read data from the peer. */
- public InputStream getInputStream() {
- return in;
- }
-
- /**
- * Returns an output stream that can be used to write data to the peer.
- *
- * @throws IllegalStateException if this stream was initiated by the peer
- * and a {@link #reply} has not yet been sent.
- */
- public OutputStream getOutputStream() {
- synchronized (this) {
- if (responseHeaders == null && !isLocallyInitiated()) {
- throw new IllegalStateException("reply before requesting the output stream");
- }
- }
- return out;
- }
-
- /**
- * Abnormally terminate this stream. This blocks until the {@code RST_STREAM}
- * frame has been transmitted.
- */
- public void close(int rstStatusCode) throws IOException {
- if (!closeInternal(rstStatusCode)) {
- return; // Already closed.
- }
- connection.writeSynReset(id, rstStatusCode);
- }
-
- /**
- * Abnormally terminate this stream. This enqueues a {@code RST_STREAM}
- * frame and returns immediately.
- */
- public void closeLater(int rstStatusCode) {
- if (!closeInternal(rstStatusCode)) {
- return; // Already closed.
- }
- connection.writeSynResetLater(id, rstStatusCode);
- }
-
- /** Returns true if this stream was closed. */
- private boolean closeInternal(int rstStatusCode) {
- assert (!Thread.holdsLock(this));
- synchronized (this) {
- if (this.rstStatusCode != -1) {
- return false;
- }
- if (in.finished && out.finished) {
- return false;
- }
- this.rstStatusCode = rstStatusCode;
- notifyAll();
- }
- connection.removeStream(id);
- return true;
- }
-
- void receiveReply(List<String> strings) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- boolean streamInUseError = false;
- boolean open = true;
- synchronized (this) {
- if (isLocallyInitiated() && responseHeaders == null) {
- responseHeaders = strings;
- open = isOpen();
- notifyAll();
- } else {
- streamInUseError = true;
- }
- }
- if (streamInUseError) {
- closeLater(SpdyStream.RST_STREAM_IN_USE);
- } else if (!open) {
- connection.removeStream(id);
- }
- }
-
- void receiveHeaders(List<String> headers) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- boolean protocolError = false;
- synchronized (this) {
- if (responseHeaders != null) {
- List<String> newHeaders = new ArrayList<String>();
- newHeaders.addAll(responseHeaders);
- newHeaders.addAll(headers);
- this.responseHeaders = newHeaders;
- } else {
- protocolError = true;
- }
- }
- if (protocolError) {
- closeLater(SpdyStream.RST_PROTOCOL_ERROR);
- }
- }
-
- void receiveData(InputStream in, int length) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- this.in.receive(in, length);
- }
-
- void receiveFin() {
- assert (!Thread.holdsLock(SpdyStream.this));
- boolean open;
- synchronized (this) {
- this.in.finished = true;
- open = isOpen();
- notifyAll();
- }
- if (!open) {
- connection.removeStream(id);
- }
- }
-
- synchronized void receiveRstStream(int statusCode) {
- if (rstStatusCode == -1) {
- rstStatusCode = statusCode;
- notifyAll();
- }
- }
-
- private void setSettings(Settings settings) {
- assert (Thread.holdsLock(connection)); // Because 'settings' is guarded by 'connection'.
- this.writeWindowSize =
- settings != null ? settings.getInitialWindowSize(Settings.DEFAULT_INITIAL_WINDOW_SIZE)
- : Settings.DEFAULT_INITIAL_WINDOW_SIZE;
- }
-
- void receiveSettings(Settings settings) {
- assert (Thread.holdsLock(this));
- setSettings(settings);
- notifyAll();
- }
-
- synchronized void receiveWindowUpdate(int deltaWindowSize) {
- out.unacknowledgedBytes -= deltaWindowSize;
- notifyAll();
- }
-
- private String rstStatusString() {
- return rstStatusCode > 0 && rstStatusCode < STATUS_CODE_NAMES.length
- ? STATUS_CODE_NAMES[rstStatusCode] : Integer.toString(rstStatusCode);
- }
-
- int getPriority() {
- return priority;
- }
-
- int getSlot() {
- return slot;
- }
-
- /**
- * An input stream that reads the incoming data frames of a stream. Although
- * this class uses synchronization to safely receive incoming data frames,
- * it is not intended for use by multiple readers.
- */
- private final class SpdyDataInputStream extends InputStream {
- // Store incoming data bytes in a circular buffer. When the buffer is
- // empty, pos == -1. Otherwise pos is the first byte to read and limit
- // is the first byte to write.
- //
- // { - - - X X X X - - - }
- // ^ ^
- // pos limit
- //
- // { X X X - - - - X X X }
- // ^ ^
- // limit pos
-
- private final byte[] buffer = new byte[Settings.DEFAULT_INITIAL_WINDOW_SIZE];
-
- /** the next byte to be read, or -1 if the buffer is empty. Never buffer.length */
- private int pos = -1;
-
- /** the last byte to be read. Never buffer.length */
- private int limit;
-
- /** True if the caller has closed this stream. */
- private boolean closed;
-
- /**
- * True if either side has cleanly shut down this stream. We will
- * receive no more bytes beyond those already in the buffer.
- */
- private boolean finished;
-
- /**
- * The total number of bytes consumed by the application (with {@link
- * #read}), but not yet acknowledged by sending a {@code WINDOW_UPDATE}
- * frame.
- */
- private int unacknowledgedBytes = 0;
-
- @Override public int available() throws IOException {
- synchronized (SpdyStream.this) {
- checkNotClosed();
- if (pos == -1) {
- return 0;
- } else if (limit > pos) {
- return limit - pos;
- } else {
- return limit + (buffer.length - pos);
- }
- }
- }
-
- @Override public int read() throws IOException {
- return Util.readSingleByte(this);
- }
-
- @Override public int read(byte[] b, int offset, int count) throws IOException {
- synchronized (SpdyStream.this) {
- checkOffsetAndCount(b.length, offset, count);
- waitUntilReadable();
- checkNotClosed();
-
- if (pos == -1) {
- return -1;
- }
-
- int copied = 0;
-
- // drain from [pos..buffer.length)
- if (limit <= pos) {
- int bytesToCopy = Math.min(count, buffer.length - pos);
- System.arraycopy(buffer, pos, b, offset, bytesToCopy);
- pos += bytesToCopy;
- copied += bytesToCopy;
- if (pos == buffer.length) {
- pos = 0;
- }
- }
-
- // drain from [pos..limit)
- if (copied < count) {
- int bytesToCopy = Math.min(limit - pos, count - copied);
- System.arraycopy(buffer, pos, b, offset + copied, bytesToCopy);
- pos += bytesToCopy;
- copied += bytesToCopy;
- }
-
- // Flow control: notify the peer that we're ready for more data!
- unacknowledgedBytes += copied;
- if (unacknowledgedBytes >= WINDOW_UPDATE_THRESHOLD) {
- connection.writeWindowUpdateLater(id, unacknowledgedBytes);
- unacknowledgedBytes = 0;
- }
-
- if (pos == limit) {
- pos = -1;
- limit = 0;
- }
-
- return copied;
- }
- }
-
- /**
- * Returns once the input stream is either readable or finished. Throws
- * a {@link SocketTimeoutException} if the read timeout elapses before
- * that happens.
- */
- private void waitUntilReadable() throws IOException {
- long start = 0;
- long remaining = 0;
- if (readTimeoutMillis != 0) {
- start = (System.nanoTime() / 1000000);
- remaining = readTimeoutMillis;
- }
- try {
- while (pos == -1 && !finished && !closed && rstStatusCode == -1) {
- if (readTimeoutMillis == 0) {
- SpdyStream.this.wait();
- } else if (remaining > 0) {
- SpdyStream.this.wait(remaining);
- remaining = start + readTimeoutMillis - (System.nanoTime() / 1000000);
- } else {
- throw new SocketTimeoutException();
- }
- }
- } catch (InterruptedException e) {
- throw new InterruptedIOException();
- }
- }
-
- void receive(InputStream in, int byteCount) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
-
- if (byteCount == 0) {
- return;
- }
-
- int pos;
- int limit;
- int firstNewByte;
- boolean finished;
- boolean flowControlError;
- synchronized (SpdyStream.this) {
- finished = this.finished;
- pos = this.pos;
- firstNewByte = this.limit;
- limit = this.limit;
- flowControlError = byteCount > buffer.length - available();
- }
-
- // If the peer sends more data than we can handle, discard it and close the connection.
- if (flowControlError) {
- Util.skipByReading(in, byteCount);
- closeLater(SpdyStream.RST_FLOW_CONTROL_ERROR);
- return;
- }
-
- // Discard data received after the stream is finished. It's probably a benign race.
- if (finished) {
- Util.skipByReading(in, byteCount);
- return;
- }
-
- // Fill the buffer without holding any locks. First fill [limit..buffer.length) if that
- // won't overwrite unread data. Then fill [limit..pos). We can't hold a lock, otherwise
- // writes will be blocked until reads complete.
- if (pos < limit) {
- int firstCopyCount = Math.min(byteCount, buffer.length - limit);
- Util.readFully(in, buffer, limit, firstCopyCount);
- limit += firstCopyCount;
- byteCount -= firstCopyCount;
- if (limit == buffer.length) {
- limit = 0;
- }
- }
- if (byteCount > 0) {
- Util.readFully(in, buffer, limit, byteCount);
- limit += byteCount;
- }
-
- synchronized (SpdyStream.this) {
- // Update the new limit, and mark the position as readable if necessary.
- this.limit = limit;
- if (this.pos == -1) {
- this.pos = firstNewByte;
- SpdyStream.this.notifyAll();
- }
- }
- }
-
- @Override public void close() throws IOException {
- synchronized (SpdyStream.this) {
- closed = true;
- SpdyStream.this.notifyAll();
- }
- cancelStreamIfNecessary();
- }
-
- private void checkNotClosed() throws IOException {
- if (closed) {
- throw new IOException("stream closed");
- }
- if (rstStatusCode != -1) {
- throw new IOException("stream was reset: " + rstStatusString());
- }
- }
- }
-
- private void cancelStreamIfNecessary() throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- boolean open;
- boolean cancel;
- synchronized (this) {
- cancel = !in.finished && in.closed && (out.finished || out.closed);
- open = isOpen();
- }
- if (cancel) {
- // RST this stream to prevent additional data from being sent. This
- // is safe because the input stream is closed (we won't use any
- // further bytes) and the output stream is either finished or closed
- // (so RSTing both streams doesn't cause harm).
- SpdyStream.this.close(RST_CANCEL);
- } else if (!open) {
- connection.removeStream(id);
- }
- }
-
- /**
- * An output stream that writes outgoing data frames of a stream. This class
- * is not thread safe.
- */
- private final class SpdyDataOutputStream extends OutputStream {
- private final byte[] buffer = new byte[8192];
- private int pos = DATA_FRAME_HEADER_LENGTH;
-
- /** True if the caller has closed this stream. */
- private boolean closed;
-
- /**
- * True if either side has cleanly shut down this stream. We shall send
- * no more bytes.
- */
- private boolean finished;
-
- /**
- * The total number of bytes written out to the peer, but not yet
- * acknowledged with an incoming {@code WINDOW_UPDATE} frame. Writes
- * block if they cause this to exceed the {@code WINDOW_SIZE}.
- */
- private int unacknowledgedBytes = 0;
-
- @Override public void write(int b) throws IOException {
- Util.writeSingleByte(this, b);
- }
-
- @Override public void write(byte[] bytes, int offset, int count) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- checkOffsetAndCount(bytes.length, offset, count);
- checkNotClosed();
-
- while (count > 0) {
- if (pos == buffer.length) {
- writeFrame(false);
- }
- int bytesToCopy = Math.min(count, buffer.length - pos);
- System.arraycopy(bytes, offset, buffer, pos, bytesToCopy);
- pos += bytesToCopy;
- offset += bytesToCopy;
- count -= bytesToCopy;
- }
- }
-
- @Override public void flush() throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- checkNotClosed();
- if (pos > DATA_FRAME_HEADER_LENGTH) {
- writeFrame(false);
- connection.flush();
- }
- }
-
- @Override public void close() throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
- synchronized (SpdyStream.this) {
- if (closed) {
- return;
- }
- closed = true;
- }
- writeFrame(true);
- connection.flush();
- cancelStreamIfNecessary();
- }
-
- private void writeFrame(boolean last) throws IOException {
- assert (!Thread.holdsLock(SpdyStream.this));
-
- int length = pos - DATA_FRAME_HEADER_LENGTH;
- synchronized (SpdyStream.this) {
- waitUntilWritable(length, last);
- unacknowledgedBytes += length;
- }
- int flags = 0;
- if (last) {
- flags |= SpdyConnection.FLAG_FIN;
- }
- pokeInt(buffer, 0, id & 0x7fffffff, BIG_ENDIAN);
- pokeInt(buffer, 4, (flags & 0xff) << 24 | length & 0xffffff, BIG_ENDIAN);
- connection.writeFrame(buffer, 0, pos);
- pos = DATA_FRAME_HEADER_LENGTH;
- }
-
- /**
- * Returns once the peer is ready to receive {@code count} bytes.
- *
- * @throws IOException if the stream was finished or closed, or the
- * thread was interrupted.
- */
- private void waitUntilWritable(int count, boolean last) throws IOException {
- try {
- while (unacknowledgedBytes + count >= writeWindowSize) {
- SpdyStream.this.wait(); // Wait until we receive a WINDOW_UPDATE.
-
- // The stream may have been closed or reset while we were waiting!
- if (!last && closed) {
- throw new IOException("stream closed");
- } else if (finished) {
- throw new IOException("stream finished");
- } else if (rstStatusCode != -1) {
- throw new IOException("stream was reset: " + rstStatusString());
- }
- }
- } catch (InterruptedException e) {
- throw new InterruptedIOException();
- }
- }
-
- private void checkNotClosed() throws IOException {
- synchronized (SpdyStream.this) {
- if (closed) {
- throw new IOException("stream closed");
- } else if (finished) {
- throw new IOException("stream finished");
- } else if (rstStatusCode != -1) {
- throw new IOException("stream was reset: " + rstStatusString());
- }
- }
- }
- }
-}