cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From na...@apache.org
Subject [11/33] CB-5799 Update version of OkHTTP to 1.3
Date Mon, 03 Feb 2014 18:37:24 GMT
http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/HttpsEngine.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/HttpsEngine.java b/framework/src/com/squareup/okhttp/internal/http/HttpsEngine.java
new file mode 100755
index 0000000..2bc1d68
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/http/HttpsEngine.java
@@ -0,0 +1,72 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.Connection;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.TunnelRequest;
+import java.io.IOException;
+import java.net.CacheResponse;
+import java.net.SecureCacheResponse;
+import java.net.URL;
+import javax.net.ssl.SSLSocket;
+
+import static com.squareup.okhttp.internal.Util.getEffectivePort;
+
+public final class HttpsEngine extends HttpEngine {
+  /**
+   * Stash of HttpsEngine.connection.socket to implement requests like {@code
+   * HttpsURLConnection#getCipherSuite} even after the connection has been
+   * recycled.
+   */
+  private SSLSocket sslSocket;
+
+  public HttpsEngine(OkHttpClient client, Policy policy, String method, RawHeaders requestHeaders,
+      Connection connection, RetryableOutputStream requestBody) throws IOException {
+    super(client, policy, method, requestHeaders, connection, requestBody);
+    this.sslSocket = connection != null ? (SSLSocket) connection.getSocket() : null;
+  }
+
+  @Override protected void connected(Connection connection) {
+    this.sslSocket = (SSLSocket) connection.getSocket();
+    super.connected(connection);
+  }
+
+  @Override protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
+    return cacheResponse instanceof SecureCacheResponse;
+  }
+
+  @Override protected boolean includeAuthorityInRequestLine() {
+    // Even if there is a proxy, it isn't involved. Always request just the path.
+    return false;
+  }
+
+  public SSLSocket getSslSocket() {
+    return sslSocket;
+  }
+
+  @Override protected TunnelRequest getTunnelConfig() {
+    String userAgent = requestHeaders.getUserAgent();
+    if (userAgent == null) {
+      userAgent = getDefaultUserAgent();
+    }
+
+    URL url = policy.getURL();
+    return new TunnelRequest(url.getHost(), getEffectivePort(url), userAgent,
+        requestHeaders.getProxyAuthorization());
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java b/framework/src/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java
old mode 100644
new mode 100755
index 235f862..e64fb98
--- a/framework/src/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java
+++ b/framework/src/com/squareup/okhttp/internal/http/HttpsURLConnectionImpl.java
@@ -16,14 +16,11 @@
  */
 package com.squareup.okhttp.internal.http;
 
-import com.squareup.okhttp.Connection;
+import android.annotation.SuppressLint;
 import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Route;
-import com.squareup.okhttp.TunnelRequest;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.net.CacheResponse;
 import java.net.HttpURLConnection;
 import java.net.ProtocolException;
 import java.net.SecureCacheResponse;
@@ -33,24 +30,20 @@ import java.security.Principal;
 import java.security.cert.Certificate;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 
-import static com.squareup.okhttp.internal.Util.getEffectivePort;
-
 public final class HttpsURLConnectionImpl extends HttpsURLConnection {
 
   /** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl. */
   private final HttpUrlConnectionDelegate delegate;
 
-  public HttpsURLConnectionImpl(URL url, OkHttpClient client, OkResponseCache responseCache,
-      Set<Route> failedRoutes) {
+  public HttpsURLConnectionImpl(URL url, OkHttpClient client) {
     super(url);
-    delegate = new HttpUrlConnectionDelegate(url, client, responseCache, failedRoutes);
+    delegate = new HttpUrlConnectionDelegate(url, client);
   }
 
   @Override public String getCipherSuite() {
@@ -120,294 +113,247 @@ public final class HttpsURLConnectionImpl extends HttpsURLConnection {
   }
 
   private SSLSocket getSslSocket() {
-    if (delegate.httpEngine == null || delegate.httpEngine.sentRequestMillis == -1) {
+    if (delegate.httpEngine == null || !delegate.httpEngine.connected) {
       throw new IllegalStateException("Connection has not yet been established");
     }
     return delegate.httpEngine instanceof HttpsEngine
-        ? ((HttpsEngine) delegate.httpEngine).sslSocket
+        ? ((HttpsEngine) delegate.httpEngine).getSslSocket()
         : null; // Not HTTPS! Probably an https:// to http:// redirect.
   }
 
-  @Override
-  public void disconnect() {
+  @Override public void disconnect() {
     delegate.disconnect();
   }
 
-  @Override
-  public InputStream getErrorStream() {
+  @Override public InputStream getErrorStream() {
     return delegate.getErrorStream();
   }
 
-  @Override
-  public String getRequestMethod() {
+  @Override public String getRequestMethod() {
     return delegate.getRequestMethod();
   }
 
-  @Override
-  public int getResponseCode() throws IOException {
+  @Override public int getResponseCode() throws IOException {
     return delegate.getResponseCode();
   }
 
-  @Override
-  public String getResponseMessage() throws IOException {
+  @Override public String getResponseMessage() throws IOException {
     return delegate.getResponseMessage();
   }
 
-  @Override
-  public void setRequestMethod(String method) throws ProtocolException {
+  @Override public void setRequestMethod(String method) throws ProtocolException {
     delegate.setRequestMethod(method);
   }
 
-  @Override
-  public boolean usingProxy() {
+  @Override public boolean usingProxy() {
     return delegate.usingProxy();
   }
 
-  @Override
-  public boolean getInstanceFollowRedirects() {
+  @Override public boolean getInstanceFollowRedirects() {
     return delegate.getInstanceFollowRedirects();
   }
 
-  @Override
-  public void setInstanceFollowRedirects(boolean followRedirects) {
+  @Override public void setInstanceFollowRedirects(boolean followRedirects) {
     delegate.setInstanceFollowRedirects(followRedirects);
   }
 
-  @Override
-  public void connect() throws IOException {
+  @Override public void connect() throws IOException {
     connected = true;
     delegate.connect();
   }
 
-  @Override
-  public boolean getAllowUserInteraction() {
+  @Override public boolean getAllowUserInteraction() {
     return delegate.getAllowUserInteraction();
   }
 
-  @Override
-  public Object getContent() throws IOException {
+  @Override public Object getContent() throws IOException {
     return delegate.getContent();
   }
 
   @SuppressWarnings("unchecked") // Spec does not generify
-  @Override
-  public Object getContent(Class[] types) throws IOException {
+  @Override public Object getContent(Class[] types) throws IOException {
     return delegate.getContent(types);
   }
 
-  @Override
-  public String getContentEncoding() {
+  @Override public String getContentEncoding() {
     return delegate.getContentEncoding();
   }
 
-  @Override
-  public int getContentLength() {
+  @Override public int getContentLength() {
     return delegate.getContentLength();
   }
 
-  @Override
-  public String getContentType() {
+  @Override public String getContentType() {
     return delegate.getContentType();
   }
 
-  @Override
-  public long getDate() {
+  @Override public long getDate() {
     return delegate.getDate();
   }
 
-  @Override
-  public boolean getDefaultUseCaches() {
+  @Override public boolean getDefaultUseCaches() {
     return delegate.getDefaultUseCaches();
   }
 
-  @Override
-  public boolean getDoInput() {
+  @Override public boolean getDoInput() {
     return delegate.getDoInput();
   }
 
-  @Override
-  public boolean getDoOutput() {
+  @Override public boolean getDoOutput() {
     return delegate.getDoOutput();
   }
 
-  @Override
-  public long getExpiration() {
+  @Override public long getExpiration() {
     return delegate.getExpiration();
   }
 
-  @Override
-  public String getHeaderField(int pos) {
+  @Override public String getHeaderField(int pos) {
     return delegate.getHeaderField(pos);
   }
 
-  @Override
-  public Map<String, List<String>> getHeaderFields() {
+  @Override public Map<String, List<String>> getHeaderFields() {
     return delegate.getHeaderFields();
   }
 
-  @Override
-  public Map<String, List<String>> getRequestProperties() {
+  @Override public Map<String, List<String>> getRequestProperties() {
     return delegate.getRequestProperties();
   }
 
-  @Override
-  public void addRequestProperty(String field, String newValue) {
+  @Override public void addRequestProperty(String field, String newValue) {
     delegate.addRequestProperty(field, newValue);
   }
 
-  @Override
-  public String getHeaderField(String key) {
+  @Override public String getHeaderField(String key) {
     return delegate.getHeaderField(key);
   }
 
-  @Override
-  public long getHeaderFieldDate(String field, long defaultValue) {
+  @Override public long getHeaderFieldDate(String field, long defaultValue) {
     return delegate.getHeaderFieldDate(field, defaultValue);
   }
 
-  @Override
-  public int getHeaderFieldInt(String field, int defaultValue) {
+  @Override public int getHeaderFieldInt(String field, int defaultValue) {
     return delegate.getHeaderFieldInt(field, defaultValue);
   }
 
-  @Override
-  public String getHeaderFieldKey(int position) {
+  @Override public String getHeaderFieldKey(int position) {
     return delegate.getHeaderFieldKey(position);
   }
 
-  @Override
-  public long getIfModifiedSince() {
+  @Override public long getIfModifiedSince() {
     return delegate.getIfModifiedSince();
   }
 
-  @Override
-  public InputStream getInputStream() throws IOException {
+  @Override public InputStream getInputStream() throws IOException {
     return delegate.getInputStream();
   }
 
-  @Override
-  public long getLastModified() {
+  @Override public long getLastModified() {
     return delegate.getLastModified();
   }
 
-  @Override
-  public OutputStream getOutputStream() throws IOException {
+  @Override public OutputStream getOutputStream() throws IOException {
     return delegate.getOutputStream();
   }
 
-  @Override
-  public Permission getPermission() throws IOException {
+  @Override public Permission getPermission() throws IOException {
     return delegate.getPermission();
   }
 
-  @Override
-  public String getRequestProperty(String field) {
+  @Override public String getRequestProperty(String field) {
     return delegate.getRequestProperty(field);
   }
 
-  @Override
-  public URL getURL() {
+  @Override public URL getURL() {
     return delegate.getURL();
   }
 
-  @Override
-  public boolean getUseCaches() {
+  @Override public boolean getUseCaches() {
     return delegate.getUseCaches();
   }
 
-  @Override
-  public void setAllowUserInteraction(boolean newValue) {
+  @Override public void setAllowUserInteraction(boolean newValue) {
     delegate.setAllowUserInteraction(newValue);
   }
 
-  @Override
-  public void setDefaultUseCaches(boolean newValue) {
+  @Override public void setDefaultUseCaches(boolean newValue) {
     delegate.setDefaultUseCaches(newValue);
   }
 
-  @Override
-  public void setDoInput(boolean newValue) {
+  @Override public void setDoInput(boolean newValue) {
     delegate.setDoInput(newValue);
   }
 
-  @Override
-  public void setDoOutput(boolean newValue) {
+  @Override public void setDoOutput(boolean newValue) {
     delegate.setDoOutput(newValue);
   }
 
-  @Override
-  public void setIfModifiedSince(long newValue) {
+  @Override public void setIfModifiedSince(long newValue) {
     delegate.setIfModifiedSince(newValue);
   }
 
-  @Override
-  public void setRequestProperty(String field, String newValue) {
+  @Override public void setRequestProperty(String field, String newValue) {
     delegate.setRequestProperty(field, newValue);
   }
 
-  @Override
-  public void setUseCaches(boolean newValue) {
+  @Override public void setUseCaches(boolean newValue) {
     delegate.setUseCaches(newValue);
   }
 
-  @Override
-  public void setConnectTimeout(int timeoutMillis) {
+  @Override public void setConnectTimeout(int timeoutMillis) {
     delegate.setConnectTimeout(timeoutMillis);
   }
 
-  @Override
-  public int getConnectTimeout() {
+  @Override public int getConnectTimeout() {
     return delegate.getConnectTimeout();
   }
 
-  @Override
-  public void setReadTimeout(int timeoutMillis) {
+  @Override public void setReadTimeout(int timeoutMillis) {
     delegate.setReadTimeout(timeoutMillis);
   }
 
-  @Override
-  public int getReadTimeout() {
+  @Override public int getReadTimeout() {
     return delegate.getReadTimeout();
   }
 
-  @Override
-  public String toString() {
+  @Override public String toString() {
     return delegate.toString();
   }
 
-  @Override
-  public void setFixedLengthStreamingMode(int contentLength) {
+  @Override public void setFixedLengthStreamingMode(int contentLength) {
     delegate.setFixedLengthStreamingMode(contentLength);
   }
 
-  @Override
-  public void setChunkedStreamingMode(int chunkLength) {
+  @Override public void setChunkedStreamingMode(int chunkLength) {
     delegate.setChunkedStreamingMode(chunkLength);
   }
 
   @Override public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
-    delegate.hostnameVerifier = hostnameVerifier;
+    delegate.client.setHostnameVerifier(hostnameVerifier);
   }
 
   @Override public HostnameVerifier getHostnameVerifier() {
-    return delegate.hostnameVerifier;
+    return delegate.client.getHostnameVerifier();
   }
 
   @Override public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
-    delegate.sslSocketFactory = sslSocketFactory;
+    delegate.client.setSslSocketFactory(sslSocketFactory);
   }
 
   @Override public SSLSocketFactory getSSLSocketFactory() {
-    return delegate.sslSocketFactory;
+    return delegate.client.getSslSocketFactory();
+  }
+
+  @SuppressLint("NewApi")
+  @Override public void setFixedLengthStreamingMode(long contentLength) {
+    delegate.setFixedLengthStreamingMode(contentLength);
   }
 
   private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl {
-    private HttpUrlConnectionDelegate(URL url, OkHttpClient client, OkResponseCache responseCache,
-        Set<Route> failedRoutes) {
-      super(url, client, responseCache, failedRoutes);
+    private HttpUrlConnectionDelegate(URL url, OkHttpClient client) {
+      super(url, client);
     }
 
-    @Override protected HttpURLConnection getHttpConnectionToCache() {
+    @Override public HttpURLConnection getHttpConnectionToCache() {
       return HttpsURLConnectionImpl.this;
     }
 
@@ -417,45 +363,4 @@ public final class HttpsURLConnectionImpl extends HttpsURLConnection {
           : null;
     }
   }
-
-  public static final class HttpsEngine extends HttpEngine {
-    /**
-     * Stash of HttpsEngine.connection.socket to implement requests like
-     * {@link #getCipherSuite} even after the connection has been recycled.
-     */
-    private SSLSocket sslSocket;
-
-    /**
-     * @param policy the HttpURLConnectionImpl with connection configuration
-     */
-    public HttpsEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
-        Connection connection, RetryableOutputStream requestBody) throws IOException {
-      super(policy, method, requestHeaders, connection, requestBody);
-      this.sslSocket = connection != null ? (SSLSocket) connection.getSocket() : null;
-    }
-
-    @Override protected void connected(Connection connection) {
-      this.sslSocket = (SSLSocket) connection.getSocket();
-    }
-
-    @Override protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
-      return cacheResponse instanceof SecureCacheResponse;
-    }
-
-    @Override protected boolean includeAuthorityInRequestLine() {
-      // Even if there is a proxy, it isn't involved. Always request just the file.
-      return false;
-    }
-
-    @Override protected TunnelRequest getTunnelConfig() {
-      String userAgent = requestHeaders.getUserAgent();
-      if (userAgent == null) {
-        userAgent = getDefaultUserAgent();
-      }
-
-      URL url = policy.getURL();
-      return new TunnelRequest(url.getHost(), getEffectivePort(url), userAgent,
-          requestHeaders.getProxyAuthorization());
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/OkResponseCache.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/OkResponseCache.java b/framework/src/com/squareup/okhttp/internal/http/OkResponseCache.java
deleted file mode 100644
index 5829f02..0000000
--- a/framework/src/com/squareup/okhttp/internal/http/OkResponseCache.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 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.ResponseSource;
-import java.io.IOException;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URLConnection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An extended response cache API. Unlike {@link java.net.ResponseCache}, this
- * interface supports conditional caching and statistics.
- *
- * <p>Along with the rest of the {@code internal} package, this is not a public
- * API. Applications wishing to supply their own caches must use the more
- * limited {@link java.net.ResponseCache} interface.
- */
-public interface OkResponseCache {
-  CacheResponse get(URI uri, String requestMethod, Map<String, List<String>> requestHeaders)
-      throws IOException;
-
-  CacheRequest put(URI uri, URLConnection urlConnection) throws IOException;
-
-  /**
-   * Handles a conditional request hit by updating the stored cache response
-   * with the headers from {@code httpConnection}. The cached response body is
-   * not updated. If the stored response has changed since {@code
-   * conditionalCacheHit} was returned, this does nothing.
-   */
-  void update(CacheResponse conditionalCacheHit, HttpURLConnection connection) throws IOException;
-
-  /** Track an conditional GET that was satisfied by this cache. */
-  void trackConditionalCacheHit();
-
-  /** Track an HTTP response being satisfied by {@code source}. */
-  void trackResponse(ResponseSource source);
-}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/OkResponseCacheAdapter.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/OkResponseCacheAdapter.java b/framework/src/com/squareup/okhttp/internal/http/OkResponseCacheAdapter.java
old mode 100644
new mode 100755
index 2ac915a..5335c2b
--- a/framework/src/com/squareup/okhttp/internal/http/OkResponseCacheAdapter.java
+++ b/framework/src/com/squareup/okhttp/internal/http/OkResponseCacheAdapter.java
@@ -15,6 +15,7 @@
  */
 package com.squareup.okhttp.internal.http;
 
+import com.squareup.okhttp.OkResponseCache;
 import com.squareup.okhttp.ResponseSource;
 import java.io.IOException;
 import java.net.CacheRequest;
@@ -41,6 +42,9 @@ public final class OkResponseCacheAdapter implements OkResponseCache {
     return responseCache.put(uri, urlConnection);
   }
 
+  @Override public void maybeRemove(String requestMethod, URI uri) throws IOException {
+  }
+
   @Override public void update(CacheResponse conditionalCacheHit, HttpURLConnection connection)
       throws IOException {
   }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/Policy.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/Policy.java b/framework/src/com/squareup/okhttp/internal/http/Policy.java
new file mode 100755
index 0000000..0a29d4b
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/http/Policy.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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 java.net.HttpURLConnection;
+import java.net.Proxy;
+import java.net.URL;
+
+public interface Policy {
+  /** Returns true if HTTP response caches should be used. */
+  boolean getUseCaches();
+
+  /** Returns the HttpURLConnection instance to store in the cache. */
+  HttpURLConnection getHttpConnectionToCache();
+
+  /** Returns the current destination URL, possibly a redirect. */
+  URL getURL();
+
+  /** Returns the If-Modified-Since timestamp, or 0 if none is set. */
+  long getIfModifiedSince();
+
+  /** Returns true if a non-direct proxy is specified. */
+  boolean usingProxy();
+
+  /** @see java.net.HttpURLConnection#setChunkedStreamingMode(int) */
+  int getChunkLength();
+
+  /** @see java.net.HttpURLConnection#setFixedLengthStreamingMode(int) */
+  long getFixedContentLength();
+
+  /**
+   * Sets the current proxy that this connection is using.
+   * @see java.net.HttpURLConnection#usingProxy
+   */
+  void setSelectedProxy(Proxy proxy);
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/RawHeaders.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/RawHeaders.java b/framework/src/com/squareup/okhttp/internal/http/RawHeaders.java
old mode 100644
new mode 100755
index eba887e..8b45320
--- a/framework/src/com/squareup/okhttp/internal/http/RawHeaders.java
+++ b/framework/src/com/squareup/okhttp/internal/http/RawHeaders.java
@@ -32,6 +32,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
 
 /**
  * The HTTP status and unparsed header fields of a single HTTP message. Values
@@ -122,23 +123,6 @@ public final class RawHeaders {
     this.httpMinorVersion = httpMinorVersion;
   }
 
-  public void computeResponseStatusLineFromSpdyHeaders() throws IOException {
-    String status = null;
-    String version = null;
-    for (int i = 0; i < namesAndValues.size(); i += 2) {
-      String name = namesAndValues.get(i);
-      if (":status".equals(name)) {
-        status = namesAndValues.get(i + 1);
-      } else if (":version".equals(name)) {
-        version = namesAndValues.get(i + 1);
-      }
-    }
-    if (status == null || version == null) {
-      throw new ProtocolException("Expected ':status' and ':version' headers not present");
-    }
-    setStatusLine(version + " " + status);
-  }
-
   /**
    * @param method like "GET", "POST", "HEAD", etc.
    * @param path like "/foo/bar.html"
@@ -180,14 +164,17 @@ public final class RawHeaders {
 
   /**
    * Add an HTTP header line containing a field name, a literal colon, and a
-   * value.
+   * value. This works around empty header names and header names that start
+   * with a colon (created by old broken SPDY versions of the response cache).
    */
   public void addLine(String line) {
-    int index = line.indexOf(":");
-    if (index == -1) {
-      addLenient("", line);
-    } else {
+    int index = line.indexOf(":", 1);
+    if (index != -1) {
       addLenient(line.substring(0, index), line.substring(index + 1));
+    } else if (line.startsWith(":")) {
+      addLenient("", line.substring(1)); // Empty header name.
+    } else {
+      addLenient("", line); // No header name.
     }
   }
 
@@ -248,6 +235,15 @@ public final class RawHeaders {
     return namesAndValues.get(fieldNameIndex);
   }
 
+  /** Returns an immutable case-insensitive set of header names. */
+  public Set<String> names() {
+    TreeSet<String> result = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+    for (int i = 0; i < length(); i++) {
+      result.add(getFieldName(i));
+    }
+    return Collections.unmodifiableSet(result);
+  }
+
   /** Returns the value at {@code index} or null if that is out of range. */
   public String getValue(int index) {
     int valueIndex = index * 2 + 1;
@@ -267,6 +263,20 @@ public final class RawHeaders {
     return null;
   }
 
+  /** Returns an immutable list of the header values for {@code name}. */
+  public List<String> values(String name) {
+    List<String> result = null;
+    for (int i = 0; i < length(); i++) {
+      if (name.equalsIgnoreCase(getFieldName(i))) {
+        if (result == null) result = new ArrayList<String>(2);
+        result.add(getValue(i));
+      }
+    }
+    return result != null
+        ? Collections.unmodifiableList(result)
+        : Collections.<String>emptyList();
+  }
+
   /** @param fieldNames a case-insensitive set of HTTP header field names. */
   public RawHeaders getAll(Set<String> fieldNames) {
     RawHeaders result = new RawHeaders();
@@ -401,10 +411,13 @@ public final class RawHeaders {
     return result;
   }
 
-  public static RawHeaders fromNameValueBlock(List<String> nameValueBlock) {
+  /** Returns headers for a name value block containing a SPDY response. */
+  public static RawHeaders fromNameValueBlock(List<String> nameValueBlock) throws IOException {
     if (nameValueBlock.size() % 2 != 0) {
       throw new IllegalArgumentException("Unexpected name value block: " + nameValueBlock);
     }
+    String status = null;
+    String version = null;
     RawHeaders result = new RawHeaders();
     for (int i = 0; i < nameValueBlock.size(); i += 2) {
       String name = nameValueBlock.get(i);
@@ -414,11 +427,21 @@ public final class RawHeaders {
         if (end == -1) {
           end = values.length();
         }
-        result.namesAndValues.add(name);
-        result.namesAndValues.add(values.substring(start, end));
+        String value = values.substring(start, end);
+        if (":status".equals(name)) {
+          status = value;
+        } else if (":version".equals(name)) {
+          version = value;
+        } else {
+          result.namesAndValues.add(name);
+          result.namesAndValues.add(value);
+        }
         start = end + 1;
       }
     }
+    if (status == null) throw new ProtocolException("Expected ':status' header not present");
+    if (version == null) throw new ProtocolException("Expected ':version' header not present");
+    result.setStatusLine(version + " " + status);
     return result;
   }
 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/RequestHeaders.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/RequestHeaders.java b/framework/src/com/squareup/okhttp/internal/http/RequestHeaders.java
old mode 100644
new mode 100755
index 5ec4fcc..71c3cd0
--- a/framework/src/com/squareup/okhttp/internal/http/RequestHeaders.java
+++ b/framework/src/com/squareup/okhttp/internal/http/RequestHeaders.java
@@ -48,7 +48,7 @@ public final class RequestHeaders {
    */
   private boolean hasAuthorization;
 
-  private int contentLength = -1;
+  private long contentLength = -1;
   private String transferEncoding;
   private String userAgent;
   private String host;
@@ -157,7 +157,7 @@ public final class RequestHeaders {
     return hasAuthorization;
   }
 
-  public int getContentLength() {
+  public long getContentLength() {
     return contentLength;
   }
 
@@ -205,14 +205,26 @@ public final class RequestHeaders {
     this.transferEncoding = "chunked";
   }
 
-  public void setContentLength(int contentLength) {
+  public void setContentLength(long contentLength) {
     if (this.contentLength != -1) {
       headers.removeAll("Content-Length");
     }
-    headers.add("Content-Length", Integer.toString(contentLength));
+    headers.add("Content-Length", Long.toString(contentLength));
     this.contentLength = contentLength;
   }
 
+  /**
+   * Remove the Content-Length headers. Call this when dropping the body on a
+   * request or response, such as when a redirect changes the method from POST
+   * to GET.
+   */
+  public void removeContentLength() {
+    if (contentLength != -1) {
+      headers.removeAll("Content-Length");
+      contentLength = -1;
+    }
+  }
+
   public void setUserAgent(String userAgent) {
     if (this.userAgent != null) {
       headers.removeAll("User-Agent");
@@ -282,9 +294,24 @@ public final class RequestHeaders {
   public void addCookies(Map<String, List<String>> allCookieHeaders) {
     for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) {
       String key = entry.getKey();
-      if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) {
-        headers.addAll(key, entry.getValue());
+      if (("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key))
+          && !entry.getValue().isEmpty()) {
+        headers.add(key, buildCookieHeader(entry.getValue()));
       }
     }
   }
+
+  /**
+   * Send all cookies in one big header, as recommended by
+   * <a href="http://tools.ietf.org/html/rfc6265#section-4.2.1">RFC 6265</a>.
+   */
+  private String buildCookieHeader(List<String> cookies) {
+    if (cookies.size() == 1) return cookies.get(0);
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < cookies.size(); i++) {
+      if (i > 0) sb.append("; ");
+      sb.append(cookies.get(i));
+    }
+    return sb.toString();
+  }
 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/ResponseHeaders.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/ResponseHeaders.java b/framework/src/com/squareup/okhttp/internal/http/ResponseHeaders.java
old mode 100644
new mode 100755
index 2ab564d..69e8656
--- a/framework/src/com/squareup/okhttp/internal/http/ResponseHeaders.java
+++ b/framework/src/com/squareup/okhttp/internal/http/ResponseHeaders.java
@@ -17,6 +17,7 @@
 package com.squareup.okhttp.internal.http;
 
 import com.squareup.okhttp.ResponseSource;
+import com.squareup.okhttp.internal.Platform;
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URI;
@@ -34,13 +35,16 @@ import static com.squareup.okhttp.internal.Util.equal;
 public final class ResponseHeaders {
 
   /** HTTP header name for the local time when the request was sent. */
-  private static final String SENT_MILLIS = "X-Android-Sent-Millis";
+  private static final String SENT_MILLIS = Platform.get().getPrefix() + "-Sent-Millis";
 
   /** HTTP header name for the local time when the response was received. */
-  private static final String RECEIVED_MILLIS = "X-Android-Received-Millis";
+  private static final String RECEIVED_MILLIS = Platform.get().getPrefix() + "-Received-Millis";
 
   /** HTTP synthetic header with the response source. */
-  static final String RESPONSE_SOURCE = "X-Android-Response-Source";
+  static final String RESPONSE_SOURCE = Platform.get().getPrefix() + "-Response-Source";
+
+  /** HTTP synthetic header with the selected transport (spdy/3, http/1.1, etc). */
+  static final String SELECTED_TRANSPORT = Platform.get().getPrefix() + "-Selected-Transport";
 
   private final URI uri;
   private final RawHeaders headers;
@@ -110,8 +114,9 @@ public final class ResponseHeaders {
 
   private String contentEncoding;
   private String transferEncoding;
-  private int contentLength = -1;
+  private long contentLength = -1;
   private String connection;
+  private String contentType;
 
   public ResponseHeaders(URI uri, RawHeaders headers) {
     this.uri = uri;
@@ -168,9 +173,11 @@ public final class ResponseHeaders {
         transferEncoding = value;
       } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
         try {
-          contentLength = Integer.parseInt(value);
+          contentLength = Long.parseLong(value);
         } catch (NumberFormatException ignored) {
         }
+      } else if ("Content-Type".equalsIgnoreCase(fieldName)) {
+        contentType = value;
       } else if ("Connection".equalsIgnoreCase(fieldName)) {
         connection = value;
       } else if (SENT_MILLIS.equalsIgnoreCase(fieldName)) {
@@ -259,10 +266,14 @@ public final class ResponseHeaders {
     return contentEncoding;
   }
 
-  public int getContentLength() {
+  public long getContentLength() {
     return contentLength;
   }
 
+  public String getContentType() {
+    return contentType;
+  }
+
   public String getConnection() {
     return connection;
   }
@@ -278,6 +289,10 @@ public final class ResponseHeaders {
     headers.set(RESPONSE_SOURCE, responseSource.toString() + " " + headers.getResponseCode());
   }
 
+  public void setTransport(String transport) {
+    headers.set(SELECTED_TRANSPORT, transport);
+  }
+
   /**
    * Returns the current age of the response, in milliseconds. The calculation
    * is specified by RFC 2616, 13.2.3 Age Calculations.

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/RetryableOutputStream.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/RetryableOutputStream.java b/framework/src/com/squareup/okhttp/internal/http/RetryableOutputStream.java
old mode 100644
new mode 100755

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java b/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
old mode 100644
new mode 100755
index ce0a71d..1055e4f
--- a/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
+++ b/framework/src/com/squareup/okhttp/internal/http/RouteSelector.java
@@ -19,6 +19,7 @@ import com.squareup.okhttp.Address;
 import com.squareup.okhttp.Connection;
 import com.squareup.okhttp.ConnectionPool;
 import com.squareup.okhttp.Route;
+import com.squareup.okhttp.RouteDatabase;
 import com.squareup.okhttp.internal.Dns;
 import java.io.IOException;
 import java.net.InetAddress;
@@ -32,8 +33,6 @@ 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;
 
@@ -55,7 +54,7 @@ public final class RouteSelector {
   private final ProxySelector proxySelector;
   private final ConnectionPool pool;
   private final Dns dns;
-  private final Set<Route> failedRoutes;
+  private final RouteDatabase routeDatabase;
 
   /* The most recently attempted route. */
   private Proxy lastProxy;
@@ -78,13 +77,13 @@ public final class RouteSelector {
   private final List<Route> postponedRoutes;
 
   public RouteSelector(Address address, URI uri, ProxySelector proxySelector, ConnectionPool pool,
-      Dns dns, Set<Route> failedRoutes) {
+      Dns dns, RouteDatabase routeDatabase) {
     this.address = address;
     this.uri = uri;
     this.proxySelector = proxySelector;
     this.pool = pool;
     this.dns = dns;
-    this.failedRoutes = failedRoutes;
+    this.routeDatabase = routeDatabase;
     this.postponedRoutes = new LinkedList<Route>();
 
     resetNextProxy(uri, address.getProxy());
@@ -103,11 +102,11 @@ public final class RouteSelector {
    *
    * @throws NoSuchElementException if there are no more routes to attempt.
    */
-  public Connection next() throws IOException {
+  public Connection next(String method) throws IOException {
     // Always prefer pooled connections over new connections.
-    Connection pooled = pool.get(address);
-    if (pooled != null) {
-      return pooled;
+    for (Connection pooled; (pooled = pool.get(address)) != null; ) {
+      if (method.equals("GET") || pooled.isReadable()) return pooled;
+      pooled.close();
     }
 
     // Compute the next route to attempt.
@@ -128,11 +127,11 @@ public final class RouteSelector {
 
     boolean modernTls = nextTlsMode() == TLS_MODE_MODERN;
     Route route = new Route(address, lastProxy, lastInetSocketAddress, modernTls);
-    if (failedRoutes.contains(route)) {
+    if (routeDatabase.shouldPostpone(route)) {
       postponedRoutes.add(route);
       // We will only recurse in order to skip previously failed routes. They will be
       // tried last.
-      return next();
+      return next(method);
     }
 
     return new Connection(route);
@@ -149,12 +148,7 @@ public final class RouteSelector {
       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());
-    }
+    routeDatabase.failed(failedRoute, failure);
   }
 
   /** Resets {@link #nextProxy} to the first option. */

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java b/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
old mode 100644
new mode 100755
index 18ab566..471539a
--- a/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
+++ b/framework/src/com/squareup/okhttp/internal/http/SpdyTransport.java
@@ -16,6 +16,7 @@
 
 package com.squareup.okhttp.internal.http;
 
+import com.squareup.okhttp.internal.spdy.ErrorCode;
 import com.squareup.okhttp.internal.spdy.SpdyConnection;
 import com.squareup.okhttp.internal.spdy.SpdyStream;
 import java.io.IOException;
@@ -36,6 +37,10 @@ public final class SpdyTransport implements Transport {
   }
 
   @Override public OutputStream createRequestBody() throws IOException {
+    long fixedContentLength = httpEngine.policy.getFixedContentLength();
+    if (fixedContentLength != -1) {
+      httpEngine.requestHeaders.setContentLength(fixedContentLength);
+    }
     // TODO: if we aren't streaming up to the server, we should buffer the whole request
     writeRequestHeaders();
     return stream.getOutputStream();
@@ -55,7 +60,7 @@ public final class SpdyTransport implements Transport {
     boolean hasResponseBody = true;
     stream = spdyConnection.newStream(requestHeaders.toNameValueBlock(), hasRequestBody,
         hasResponseBody);
-    stream.setReadTimeout(httpEngine.policy.getReadTimeout());
+    stream.setReadTimeout(httpEngine.client.getReadTimeout());
   }
 
   @Override public void writeRequestBody(RetryableOutputStream requestBody) throws IOException {
@@ -69,24 +74,26 @@ public final class SpdyTransport implements Transport {
   @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);
+
+    ResponseHeaders headers = new ResponseHeaders(httpEngine.uri, rawHeaders);
+    headers.setTransport("spdy/3");
+    return headers;
   }
 
   @Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException {
     return new UnknownLengthHttpInputStream(stream.getInputStream(), cacheRequest, httpEngine);
   }
 
-  @Override public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
+  @Override public boolean makeReusable(boolean streamCanceled, OutputStream requestBodyOut,
       InputStream responseBodyIn) {
-    if (streamCancelled) {
+    if (streamCanceled) {
       if (stream != null) {
-        stream.closeLater(SpdyStream.RST_CANCEL);
+        stream.closeLater(ErrorCode.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
+        // 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;
       }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/Transport.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/Transport.java b/framework/src/com/squareup/okhttp/internal/http/Transport.java
old mode 100644
new mode 100755
index 518827e..d408bfe
--- a/framework/src/com/squareup/okhttp/internal/http/Transport.java
+++ b/framework/src/com/squareup/okhttp/internal/http/Transport.java
@@ -59,6 +59,6 @@ interface Transport {
   InputStream getTransferStream(CacheRequest cacheRequest) throws IOException;
 
   /** Returns true if the underlying connection can be recycled. */
-  boolean makeReusable(boolean streamReusable, OutputStream requestBodyOut,
+  boolean makeReusable(boolean streamCanceled, OutputStream requestBodyOut,
       InputStream responseBodyIn);
 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java b/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
old mode 100644
new mode 100755
index 729e0b9..ca6bb59
--- a/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
+++ b/framework/src/com/squareup/okhttp/internal/http/UnknownLengthHttpInputStream.java
@@ -25,9 +25,9 @@ import static com.squareup.okhttp.internal.Util.checkOffsetAndCount;
 final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
   private boolean inputExhausted;
 
-  UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest, HttpEngine httpEngine)
+  UnknownLengthHttpInputStream(InputStream in, CacheRequest cacheRequest, HttpEngine httpEngine)
       throws IOException {
-    super(is, httpEngine, cacheRequest);
+    super(in, httpEngine, cacheRequest);
   }
 
   @Override public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -39,7 +39,7 @@ final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
     int read = in.read(buffer, offset, count);
     if (read == -1) {
       inputExhausted = true;
-      endOfInput(false);
+      endOfInput();
       return -1;
     }
     cacheWrite(buffer, offset, read);

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/ErrorCode.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/ErrorCode.java b/framework/src/com/squareup/okhttp/internal/spdy/ErrorCode.java
new file mode 100755
index 0000000..d3a32e1
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/ErrorCode.java
@@ -0,0 +1,67 @@
+package com.squareup.okhttp.internal.spdy;
+
+public enum ErrorCode {
+  /** Not an error! For SPDY stream resets, prefer null over NO_ERROR. */
+  NO_ERROR(0, -1, 0),
+
+  PROTOCOL_ERROR(1, 1, 1),
+
+  /** A subtype of PROTOCOL_ERROR used by SPDY. */
+  INVALID_STREAM(1, 2, -1),
+
+  /** A subtype of PROTOCOL_ERROR used by SPDY. */
+  UNSUPPORTED_VERSION(1, 4, -1),
+
+  /** A subtype of PROTOCOL_ERROR used by SPDY. */
+  STREAM_IN_USE(1, 8, -1),
+
+  /** A subtype of PROTOCOL_ERROR used by SPDY. */
+  STREAM_ALREADY_CLOSED(1, 9, -1),
+
+  INTERNAL_ERROR(2, 6, 2),
+
+  FLOW_CONTROL_ERROR(3, 7, -1),
+
+  STREAM_CLOSED(5, -1, -1),
+
+  FRAME_TOO_LARGE(6, 11, -1),
+
+  REFUSED_STREAM(7, 3, -1),
+
+  CANCEL(8, 5, -1),
+
+  COMPRESSION_ERROR(9, -1, -1),
+
+  INVALID_CREDENTIALS(-1, 10, -1);
+
+  public final int httpCode;
+  public final int spdyRstCode;
+  public final int spdyGoAwayCode;
+
+  private ErrorCode(int httpCode, int spdyRstCode, int spdyGoAwayCode) {
+    this.httpCode = httpCode;
+    this.spdyRstCode = spdyRstCode;
+    this.spdyGoAwayCode = spdyGoAwayCode;
+  }
+
+  public static ErrorCode fromSpdy3Rst(int code) {
+    for (ErrorCode errorCode : ErrorCode.values()) {
+      if (errorCode.spdyRstCode == code) return errorCode;
+    }
+    return null;
+  }
+
+  public static ErrorCode fromHttp2(int code) {
+    for (ErrorCode errorCode : ErrorCode.values()) {
+      if (errorCode.httpCode == code) return errorCode;
+    }
+    return null;
+  }
+
+  public static ErrorCode fromSpdyGoAway(int code) {
+    for (ErrorCode errorCode : ErrorCode.values()) {
+      if (errorCode.spdyGoAwayCode == code) return errorCode;
+    }
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/FrameReader.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/FrameReader.java b/framework/src/com/squareup/okhttp/internal/spdy/FrameReader.java
new file mode 100755
index 0000000..1371262
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/FrameReader.java
@@ -0,0 +1,55 @@
+/*
+ * 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.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/** Reads transport frames for SPDY/3 or HTTP/2.0. */
+public interface FrameReader extends Closeable {
+  void readConnectionHeader() throws IOException;
+  boolean nextFrame(Handler handler) throws IOException;
+
+  public interface Handler {
+    void data(boolean inFinished, int streamId, InputStream in, int length) throws IOException;
+    /**
+     * Create or update incoming headers, creating the corresponding streams
+     * if necessary. Frames that trigger this are SPDY SYN_STREAM, HEADERS, and
+     * SYN_REPLY, and HTTP/2.0 HEADERS and PUSH_PROMISE.
+     *
+     * @param inFinished true if the sender will not send further frames.
+     * @param outFinished true if the receiver should not send further frames.
+     * @param streamId the stream owning these headers.
+     * @param associatedStreamId the stream that triggered the sender to create
+     *     this stream.
+     * @param priority or -1 for no priority. For SPDY, priorities range from 0
+     *     (highest) thru 7 (lowest). For HTTP/2.0, priorities range from 0
+     *     (highest) thru 2**31-1 (lowest).
+     */
+    void headers(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
+        int priority, List<String> nameValueBlock, HeadersMode headersMode);
+    void rstStream(int streamId, ErrorCode errorCode);
+    void settings(boolean clearPrevious, Settings settings);
+    void noop();
+    void ping(boolean reply, int payload1, int payload2);
+    void goAway(int lastGoodStreamId, ErrorCode errorCode);
+    void windowUpdate(int streamId, int deltaWindowSize, boolean endFlowControl);
+    void priority(int streamId, int priority);
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/FrameWriter.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/FrameWriter.java b/framework/src/com/squareup/okhttp/internal/spdy/FrameWriter.java
new file mode 100755
index 0000000..354f43d
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/FrameWriter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+/** Writes transport frames for SPDY/3 or HTTP/2.0. */
+public interface FrameWriter extends Closeable {
+  /** HTTP/2.0 only. */
+  void connectionHeader() throws IOException;
+
+  /** SPDY/3 only. */
+  void flush() throws IOException;
+  void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
+      int priority, int slot, List<String> nameValueBlock) throws IOException;
+  void synReply(boolean outFinished, int streamId, List<String> nameValueBlock) throws IOException;
+  void headers(int streamId, List<String> nameValueBlock) throws IOException;
+  void rstStream(int streamId, ErrorCode errorCode) throws IOException;
+  void data(boolean outFinished, int streamId, byte[] data) throws IOException;
+  void data(boolean outFinished, int streamId, byte[] data, int offset, int byteCount)
+      throws IOException;
+  void settings(Settings settings) throws IOException;
+  void noop() throws IOException;
+  void ping(boolean reply, int payload1, int payload2) throws IOException;
+  void goAway(int lastGoodStreamId, ErrorCode errorCode) throws IOException;
+  void windowUpdate(int streamId, int deltaWindowSize) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/HeadersMode.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/HeadersMode.java b/framework/src/com/squareup/okhttp/internal/spdy/HeadersMode.java
new file mode 100755
index 0000000..e16e176
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/HeadersMode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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;
+
+enum HeadersMode {
+  SPDY_SYN_STREAM,
+  SPDY_REPLY,
+  SPDY_HEADERS,
+  HTTP_20_HEADERS;
+
+  /** Returns true if it is an error these headers to create a new stream. */
+  public boolean failIfStreamAbsent() {
+    return this == SPDY_REPLY || this == SPDY_HEADERS;
+  }
+
+  /** Returns true if it is an error these headers to update an existing stream. */
+  public boolean failIfStreamPresent() {
+    return this == SPDY_SYN_STREAM;
+  }
+
+  /**
+   * Returns true if it is an error these headers to be the initial headers of a
+   * response.
+   */
+  public boolean failIfHeadersAbsent() {
+    return this == SPDY_HEADERS;
+  }
+
+  /**
+   * Returns true if it is an error these headers to be update existing headers
+   * of a response.
+   */
+  public boolean failIfHeadersPresent() {
+    return this == SPDY_REPLY;
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/Hpack.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Hpack.java b/framework/src/com/squareup/okhttp/internal/spdy/Hpack.java
new file mode 100755
index 0000000..c3ca8f1
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/Hpack.java
@@ -0,0 +1,371 @@
+package com.squareup.okhttp.internal.spdy;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * Read and write HPACK v03.
+ * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-03
+ */
+final class Hpack {
+
+  static class HeaderEntry {
+    private final String name;
+    private final String value;
+
+    HeaderEntry(String name, String value) {
+      this.name = name;
+      this.value = value;
+    }
+
+    // TODO: This needs to be the length in UTF-8 bytes, not the length in chars.
+    int length() {
+      return 32 + name.length() + value.length();
+    }
+  }
+
+  static final int PREFIX_5_BITS = 0x1f;
+  static final int PREFIX_6_BITS = 0x3f;
+  static final int PREFIX_7_BITS = 0x7f;
+  static final int PREFIX_8_BITS = 0xff;
+
+  static final List<HeaderEntry> INITIAL_CLIENT_TO_SERVER_HEADER_TABLE = Arrays.asList(
+      new HeaderEntry(":scheme", "http"),
+      new HeaderEntry(":scheme", "https"),
+      new HeaderEntry(":host", ""),
+      new HeaderEntry(":path", "/"),
+      new HeaderEntry(":method", "GET"),
+      new HeaderEntry("accept", ""),
+      new HeaderEntry("accept-charset", ""),
+      new HeaderEntry("accept-encoding", ""),
+      new HeaderEntry("accept-language", ""),
+      new HeaderEntry("cookie", ""),
+      new HeaderEntry("if-modified-since", ""),
+      new HeaderEntry("user-agent", ""),
+      new HeaderEntry("referer", ""),
+      new HeaderEntry("authorization", ""),
+      new HeaderEntry("allow", ""),
+      new HeaderEntry("cache-control", ""),
+      new HeaderEntry("connection", ""),
+      new HeaderEntry("content-length", ""),
+      new HeaderEntry("content-type", ""),
+      new HeaderEntry("date", ""),
+      new HeaderEntry("expect", ""),
+      new HeaderEntry("from", ""),
+      new HeaderEntry("if-match", ""),
+      new HeaderEntry("if-none-match", ""),
+      new HeaderEntry("if-range", ""),
+      new HeaderEntry("if-unmodified-since", ""),
+      new HeaderEntry("max-forwards", ""),
+      new HeaderEntry("proxy-authorization", ""),
+      new HeaderEntry("range", ""),
+      new HeaderEntry("via", "")
+  );
+
+  static final List<HeaderEntry> INITIAL_SERVER_TO_CLIENT_HEADER_TABLE = Arrays.asList(
+      new HeaderEntry(":status", "200"),
+      new HeaderEntry("age", ""),
+      new HeaderEntry("cache-control", ""),
+      new HeaderEntry("content-length", ""),
+      new HeaderEntry("content-type", ""),
+      new HeaderEntry("date", ""),
+      new HeaderEntry("etag", ""),
+      new HeaderEntry("expires", ""),
+      new HeaderEntry("last-modified", ""),
+      new HeaderEntry("server", ""),
+      new HeaderEntry("set-cookie", ""),
+      new HeaderEntry("vary", ""),
+      new HeaderEntry("via", ""),
+      new HeaderEntry("access-control-allow-origin", ""),
+      new HeaderEntry("accept-ranges", ""),
+      new HeaderEntry("allow", ""),
+      new HeaderEntry("connection", ""),
+      new HeaderEntry("content-disposition", ""),
+      new HeaderEntry("content-encoding", ""),
+      new HeaderEntry("content-language", ""),
+      new HeaderEntry("content-location", ""),
+      new HeaderEntry("content-range", ""),
+      new HeaderEntry("link", ""),
+      new HeaderEntry("location", ""),
+      new HeaderEntry("proxy-authenticate", ""),
+      new HeaderEntry("refresh", ""),
+      new HeaderEntry("retry-after", ""),
+      new HeaderEntry("strict-transport-security", ""),
+      new HeaderEntry("transfer-encoding", ""),
+      new HeaderEntry("www-authenticate", "")
+  );
+
+  // Update these when initial tables change to sum of each entry length.
+  static final int INITIAL_CLIENT_TO_SERVER_HEADER_TABLE_LENGTH = 1262;
+  static final int INITIAL_SERVER_TO_CLIENT_HEADER_TABLE_LENGTH = 1304;
+
+  private Hpack() {
+  }
+
+  static class Reader {
+    private final long maxBufferSize = 4096; // TODO: needs to come from settings.
+    private final DataInputStream in;
+
+    private final BitSet referenceSet = new BitSet();
+    private final List<HeaderEntry> headerTable;
+    private final List<String> emittedHeaders = new ArrayList<String>();
+    private long bufferSize = 0;
+    private long bytesLeft = 0;
+
+    Reader(DataInputStream in, boolean client) {
+      this.in = in;
+      if (client) {  // we are reading from the server
+        this.headerTable = new ArrayList<HeaderEntry>(INITIAL_SERVER_TO_CLIENT_HEADER_TABLE);
+        this.bufferSize = INITIAL_SERVER_TO_CLIENT_HEADER_TABLE_LENGTH;
+      } else {
+        this.headerTable = new ArrayList<HeaderEntry>(INITIAL_CLIENT_TO_SERVER_HEADER_TABLE);
+        this.bufferSize = INITIAL_CLIENT_TO_SERVER_HEADER_TABLE_LENGTH;
+      }
+    }
+
+    /**
+     * Read {@code byteCount} bytes of headers from the source stream into the
+     * set of emitted headers.
+     */
+    public void readHeaders(int byteCount) throws IOException {
+      bytesLeft += byteCount;
+      // TODO: limit to 'byteCount' bytes?
+
+      while (bytesLeft > 0) {
+        int b = readByte();
+
+        if ((b & 0x80) != 0) {
+          int index = readInt(b, PREFIX_7_BITS);
+          readIndexedHeader(index);
+        } else if (b == 0x60) {
+          readLiteralHeaderWithoutIndexingNewName();
+        } else if ((b & 0xe0) == 0x60) {
+          int index = readInt(b, PREFIX_5_BITS);
+          readLiteralHeaderWithoutIndexingIndexedName(index - 1);
+        } else if (b == 0x40) {
+          readLiteralHeaderWithIncrementalIndexingNewName();
+        } else if ((b & 0xe0) == 0x40) {
+          int index = readInt(b, PREFIX_5_BITS);
+          readLiteralHeaderWithIncrementalIndexingIndexedName(index - 1);
+        } else if (b == 0) {
+          readLiteralHeaderWithSubstitutionIndexingNewName();
+        } else if ((b & 0xc0) == 0) {
+          int index = readInt(b, PREFIX_6_BITS);
+          readLiteralHeaderWithSubstitutionIndexingIndexedName(index - 1);
+        } else {
+          throw new AssertionError();
+        }
+      }
+    }
+
+    public void emitReferenceSet() {
+      for (int i = referenceSet.nextSetBit(0); i != -1; i = referenceSet.nextSetBit(i + 1)) {
+        emittedHeaders.add(getName(i));
+        emittedHeaders.add(getValue(i));
+      }
+    }
+
+    /**
+     * Returns all headers emitted since they were last cleared, then clears the
+     * emitted headers.
+     */
+    public List<String> getAndReset() {
+      List<String> result = new ArrayList<String>(emittedHeaders);
+      emittedHeaders.clear();
+      return result;
+    }
+
+    private void readIndexedHeader(int index) {
+      if (referenceSet.get(index)) {
+        referenceSet.clear(index);
+      } else {
+        referenceSet.set(index);
+      }
+    }
+
+    private void readLiteralHeaderWithoutIndexingIndexedName(int index)
+        throws IOException {
+      String name = getName(index);
+      String value = readString();
+      emittedHeaders.add(name);
+      emittedHeaders.add(value);
+    }
+
+    private void readLiteralHeaderWithoutIndexingNewName()
+        throws IOException {
+      String name = readString();
+      String value = readString();
+      emittedHeaders.add(name);
+      emittedHeaders.add(value);
+    }
+
+    private void readLiteralHeaderWithIncrementalIndexingIndexedName(int nameIndex)
+        throws IOException {
+      String name = getName(nameIndex);
+      String value = readString();
+      int index = headerTable.size(); // append to tail
+      insertIntoHeaderTable(index, new HeaderEntry(name, value));
+    }
+
+    private void readLiteralHeaderWithIncrementalIndexingNewName() throws IOException {
+      String name = readString();
+      String value = readString();
+      int index = headerTable.size(); // append to tail
+      insertIntoHeaderTable(index, new HeaderEntry(name, value));
+    }
+
+    private void readLiteralHeaderWithSubstitutionIndexingIndexedName(int nameIndex)
+        throws IOException {
+      int index = readInt(readByte(), PREFIX_8_BITS);
+      String name = getName(nameIndex);
+      String value = readString();
+      insertIntoHeaderTable(index, new HeaderEntry(name, value));
+    }
+
+    private void readLiteralHeaderWithSubstitutionIndexingNewName() throws IOException {
+      String name = readString();
+      int index = readInt(readByte(), PREFIX_8_BITS);
+      String value = readString();
+      insertIntoHeaderTable(index, new HeaderEntry(name, value));
+    }
+
+    private String getName(int index) {
+      return headerTable.get(index).name;
+    }
+
+    private String getValue(int index) {
+      return headerTable.get(index).value;
+    }
+
+    private void insertIntoHeaderTable(int index, HeaderEntry entry) {
+      int delta = entry.length();
+      if (index != headerTable.size()) {
+        delta -= headerTable.get(index).length();
+      }
+
+      // if the new or replacement header is too big, drop all entries.
+      if (delta > maxBufferSize) {
+        headerTable.clear();
+        bufferSize = 0;
+        // emit the large header to the callback.
+        emittedHeaders.add(entry.name);
+        emittedHeaders.add(entry.value);
+        return;
+      }
+
+      // Prune headers to the required length.
+      while (bufferSize + delta > maxBufferSize) {
+        remove(0);
+        index--;
+      }
+
+      if (index < 0) { // we pruned it, so insert at beginning
+        index = 0;
+        headerTable.add(index, entry);
+      } else if (index == headerTable.size()) { // append to the end
+        headerTable.add(index, entry);
+      } else { // replace value at same position
+        headerTable.set(index, entry);
+      }
+
+      bufferSize += delta;
+      referenceSet.set(index);
+    }
+
+    private void remove(int index) {
+      bufferSize -= headerTable.remove(index).length();
+    }
+
+    private int readByte() throws IOException {
+      bytesLeft--;
+      return in.readByte() & 0xff;
+    }
+
+    int readInt(int firstByte, int prefixMask) throws IOException {
+      int prefix = firstByte & prefixMask;
+      if (prefix < prefixMask) {
+        return prefix; // This was a single byte value.
+      }
+
+      // This is a multibyte value. Read 7 bits at a time.
+      int result = prefixMask;
+      int shift = 0;
+      while (true) {
+        int b = readByte();
+        if ((b & 0x80) != 0) { // Equivalent to (b >= 128) since b is in [0..255].
+          result += (b & 0x7f) << shift;
+          shift += 7;
+        } else {
+          result += b << shift; // Last byte.
+          break;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Reads a UTF-8 encoded string. Since ASCII is a subset of UTF-8, this method
+     * may be used to read strings that are known to be ASCII-only.
+     */
+    public String readString() throws IOException {
+      int firstByte = readByte();
+      int length = readInt(firstByte, PREFIX_8_BITS);
+      byte[] encoded = new byte[length];
+      bytesLeft -= length;
+      in.readFully(encoded);
+      return new String(encoded, "UTF-8");
+    }
+  }
+
+  static class Writer {
+    private final OutputStream out;
+
+    Writer(OutputStream out) {
+      this.out = out;
+    }
+
+    public void writeHeaders(List<String> nameValueBlock) throws IOException {
+      // TODO: implement a compression strategy.
+      for (int i = 0, size = nameValueBlock.size(); i < size; i += 2) {
+        out.write(0x60); // Literal Header without Indexing - New Name.
+        writeString(nameValueBlock.get(i));
+        writeString(nameValueBlock.get(i + 1));
+      }
+    }
+
+    public void writeInt(int value, int prefixMask, int bits) throws IOException {
+      // Write the raw value for a single byte value.
+      if (value < prefixMask) {
+        out.write(bits | value);
+        return;
+      }
+
+      // Write the mask to start a multibyte value.
+      out.write(bits | prefixMask);
+      value -= prefixMask;
+
+      // Write 7 bits at a time 'til we're done.
+      while (value >= 0x80) {
+        int b = value & 0x7f;
+        out.write(b | 0x80);
+        value >>>= 7;
+      }
+      out.write(value);
+    }
+
+    /**
+     * Writes a UTF-8 encoded string. Since ASCII is a subset of UTF-8, this
+     * method can be used to write strings that are known to be ASCII-only.
+     */
+    public void writeString(String headerName) throws IOException {
+      byte[] bytes = headerName.getBytes("UTF-8");
+      writeInt(bytes.length, PREFIX_8_BITS, 0);
+      out.write(bytes);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/Http20Draft06.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Http20Draft06.java b/framework/src/com/squareup/okhttp/internal/spdy/Http20Draft06.java
new file mode 100755
index 0000000..3d53f48
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/Http20Draft06.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2013 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 com.squareup.okhttp.internal.Util;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Read and write http/2 v06 frames.
+ * http://tools.ietf.org/html/draft-ietf-httpbis-http2-06
+ */
+final class Http20Draft06 implements Variant {
+  private static final byte[] CONNECTION_HEADER;
+  static {
+    try {
+      CONNECTION_HEADER = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes("UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new AssertionError();
+    }
+  }
+
+  static final int TYPE_DATA = 0x0;
+  static final int TYPE_HEADERS = 0x1;
+  static final int TYPE_PRIORITY = 0x2;
+  static final int TYPE_RST_STREAM = 0x3;
+  static final int TYPE_SETTINGS = 0x4;
+  static final int TYPE_PUSH_PROMISE = 0x5;
+  static final int TYPE_PING = 0x6;
+  static final int TYPE_GOAWAY = 0x7;
+  static final int TYPE_WINDOW_UPDATE = 0x9;
+  static final int TYPE_CONTINUATION = 0xa;
+
+  static final int FLAG_END_STREAM = 0x1;
+  /** Used for headers, push-promise and continuation. */
+  static final int FLAG_END_HEADERS = 0x4;
+  static final int FLAG_PRIORITY = 0x8;
+  static final int FLAG_PONG = 0x1;
+  static final int FLAG_END_FLOW_CONTROL = 0x1;
+
+  @Override public FrameReader newReader(InputStream in, boolean client) {
+    return new Reader(in, client);
+  }
+
+  @Override public FrameWriter newWriter(OutputStream out, boolean client) {
+    return new Writer(out, client);
+  }
+
+  static final class Reader implements FrameReader {
+    private final DataInputStream in;
+    private final boolean client;
+    private final Hpack.Reader hpackReader;
+
+    Reader(InputStream in, boolean client) {
+      this.in = new DataInputStream(in);
+      this.client = client;
+      this.hpackReader = new Hpack.Reader(this.in, client);
+    }
+
+    @Override public void readConnectionHeader() throws IOException {
+      if (client) return; // Nothing to read; servers don't send connection headers!
+      byte[] connectionHeader = new byte[CONNECTION_HEADER.length];
+      in.readFully(connectionHeader);
+      if (!Arrays.equals(connectionHeader, CONNECTION_HEADER)) {
+        throw ioException("Expected a connection header but was "
+            + Arrays.toString(connectionHeader));
+      }
+    }
+
+    @Override 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();
+
+      int length = (w1 & 0xffff0000) >> 16;
+      int type = (w1 & 0xff00) >> 8;
+      int flags = w1 & 0xff;
+      // boolean r = (w2 & 0x80000000) != 0; // Reserved.
+      int streamId = (w2 & 0x7fffffff);
+
+      switch (type) {
+        case TYPE_DATA:
+          readData(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_HEADERS:
+          readHeaders(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_PRIORITY:
+          readPriority(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_RST_STREAM:
+          readRstStream(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_SETTINGS:
+          readSettings(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_PUSH_PROMISE:
+          readPushPromise(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_PING:
+          readPing(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_GOAWAY:
+          readGoAway(handler, flags, length, streamId);
+          return true;
+
+        case TYPE_WINDOW_UPDATE:
+          readWindowUpdate(handler, flags, length, streamId);
+          return true;
+      }
+
+      throw new UnsupportedOperationException("TODO");
+    }
+
+    private void readHeaders(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      if (streamId == 0) throw ioException("TYPE_HEADERS streamId == 0");
+
+      boolean inFinished = (flags & FLAG_END_STREAM) != 0;
+
+      while (true) {
+        hpackReader.readHeaders(length);
+
+        if ((flags & FLAG_END_HEADERS) != 0) {
+          hpackReader.emitReferenceSet();
+          List<String> namesAndValues = hpackReader.getAndReset();
+          int priority = -1; // TODO: priority
+          handler.headers(false, inFinished, streamId, -1, priority, namesAndValues,
+              HeadersMode.HTTP_20_HEADERS);
+          return;
+        }
+
+        // Read another continuation frame.
+        int w1 = in.readInt();
+        int w2 = in.readInt();
+
+        length = (w1 & 0xffff0000) >> 16;
+        int newType = (w1 & 0xff00) >> 8;
+        flags = w1 & 0xff;
+
+        // TODO: remove in draft 8: CONTINUATION no longer sets END_STREAM
+        inFinished = (flags & FLAG_END_STREAM) != 0;
+
+        // boolean u = (w2 & 0x80000000) != 0; // Unused.
+        int newStreamId = (w2 & 0x7fffffff);
+
+        if (newType != TYPE_CONTINUATION) {
+          throw ioException("TYPE_CONTINUATION didn't have FLAG_END_HEADERS");
+        }
+        if (newStreamId != streamId) throw ioException("TYPE_CONTINUATION streamId changed");
+      }
+    }
+
+    private void readData(Handler handler, int flags, int length, int streamId) throws IOException {
+      boolean inFinished = (flags & FLAG_END_STREAM) != 0;
+      handler.data(inFinished, streamId, in, length);
+    }
+
+    private void readPriority(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      if (length != 4) throw ioException("TYPE_PRIORITY length: %d != 4", length);
+      if (streamId == 0) throw ioException("TYPE_PRIORITY streamId == 0");
+      int w1 = in.readInt();
+      // boolean r = (w1 & 0x80000000) != 0; // Reserved.
+      int priority = (w1 & 0x7fffffff);
+      handler.priority(streamId, priority);
+    }
+
+    private void readRstStream(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      if (length != 4) throw ioException("TYPE_RST_STREAM length: %d != 4", length);
+      if (streamId == 0) throw ioException("TYPE_RST_STREAM streamId == 0");
+      int errorCodeInt = in.readInt();
+      ErrorCode errorCode = ErrorCode.fromHttp2(errorCodeInt);
+      if (errorCode == null) {
+        throw ioException("TYPE_RST_STREAM unexpected error code: %d", errorCodeInt);
+      }
+      handler.rstStream(streamId, errorCode);
+    }
+
+    private void readSettings(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      if (length % 8 != 0) throw ioException("TYPE_SETTINGS length %% 8 != 0: %s", length);
+      if (streamId != 0) throw ioException("TYPE_SETTINGS streamId != 0");
+      Settings settings = new Settings();
+      for (int i = 0; i < length; i += 8) {
+        int w1 = in.readInt();
+        int value = in.readInt();
+        // int r = (w1 & 0xff000000) >>> 24; // Reserved.
+        int id = w1 & 0xffffff;
+        settings.set(id, 0, value);
+      }
+      handler.settings(false, settings);
+    }
+
+    private void readPushPromise(Handler handler, int flags, int length, int streamId) {
+      // TODO:
+    }
+
+    private void readPing(Handler handler, int flags, int length, int streamId) throws IOException {
+      if (length != 8) throw ioException("TYPE_PING length != 8: %s", length);
+      if (streamId != 0) throw ioException("TYPE_PING streamId != 0");
+      int payload1 = in.readInt();
+      int payload2 = in.readInt();
+      boolean reply = (flags & FLAG_PONG) != 0;
+      handler.ping(reply, payload1, payload2);
+    }
+
+    private void readGoAway(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      if (length < 8) throw ioException("TYPE_GOAWAY length < 8: %s", length);
+      int lastStreamId = in.readInt();
+      int errorCodeInt = in.readInt();
+      int opaqueDataLength = length - 8;
+      ErrorCode errorCode = ErrorCode.fromHttp2(errorCodeInt);
+      if (errorCode == null) {
+        throw ioException("TYPE_RST_STREAM unexpected error code: %d", errorCodeInt);
+      }
+      if (Util.skipByReading(in, opaqueDataLength) != opaqueDataLength) {
+        throw new IOException("TYPE_GOAWAY opaque data was truncated");
+      }
+      handler.goAway(lastStreamId, errorCode);
+    }
+
+    private void readWindowUpdate(Handler handler, int flags, int length, int streamId)
+        throws IOException {
+      int w1 = in.readInt();
+      // boolean r = (w1 & 0x80000000) != 0; // Reserved.
+      int windowSizeIncrement = (w1 & 0x7fffffff);
+      boolean endFlowControl = (flags & FLAG_END_FLOW_CONTROL) != 0;
+      handler.windowUpdate(streamId, windowSizeIncrement, endFlowControl);
+    }
+
+    private static IOException ioException(String message, Object... args) throws IOException {
+      throw new IOException(String.format(message, args));
+    }
+
+    @Override public void close() throws IOException {
+      in.close();
+    }
+  }
+
+  static final class Writer implements FrameWriter {
+    private final DataOutputStream out;
+    private final boolean client;
+    private final ByteArrayOutputStream hpackBuffer;
+    private final Hpack.Writer hpackWriter;
+
+    Writer(OutputStream out, boolean client) {
+      this.out = new DataOutputStream(out);
+      this.client = client;
+      this.hpackBuffer = new ByteArrayOutputStream();
+      this.hpackWriter = new Hpack.Writer(hpackBuffer);
+    }
+
+    @Override public synchronized void flush() throws IOException {
+      out.flush();
+    }
+
+    @Override public synchronized void connectionHeader() throws IOException {
+      if (!client) return; // Nothing to write; servers don't send connection headers!
+      out.write(CONNECTION_HEADER);
+    }
+
+    @Override public synchronized void synStream(boolean outFinished, boolean inFinished,
+        int streamId, int associatedStreamId, int priority, int slot, List<String> nameValueBlock)
+        throws IOException {
+      if (inFinished) throw new UnsupportedOperationException();
+      headers(outFinished, streamId, priority, nameValueBlock);
+    }
+
+    @Override public synchronized void synReply(boolean outFinished, int streamId,
+        List<String> nameValueBlock) throws IOException {
+      headers(outFinished, streamId, -1, nameValueBlock);
+    }
+
+    @Override public synchronized void headers(int streamId, List<String> nameValueBlock)
+        throws IOException {
+      headers(false, streamId, -1, nameValueBlock);
+    }
+
+    private void headers(boolean outFinished, int streamId, int priority,
+        List<String> nameValueBlock) throws IOException {
+      hpackBuffer.reset();
+      hpackWriter.writeHeaders(nameValueBlock);
+      int type = TYPE_HEADERS;
+      // TODO: implement CONTINUATION
+      int length = hpackBuffer.size();
+      int flags = FLAG_END_HEADERS;
+      if (outFinished) flags |= FLAG_END_STREAM;
+      if (priority != -1) flags |= FLAG_PRIORITY;
+      out.writeInt((length & 0xffff) << 16 | (type & 0xff) << 8 | (flags & 0xff));
+      out.writeInt(streamId & 0x7fffffff);
+      if (priority != -1) out.writeInt(priority & 0x7fffffff);
+      hpackBuffer.writeTo(out);
+    }
+
+    @Override public synchronized void rstStream(int streamId, ErrorCode errorCode)
+        throws IOException {
+      throw new UnsupportedOperationException("TODO");
+    }
+
+    @Override public void data(boolean outFinished, int streamId, byte[] data) throws IOException {
+      data(outFinished, streamId, data, 0, data.length);
+    }
+
+    @Override public synchronized void data(boolean outFinished, int streamId, byte[] data,
+        int offset, int byteCount) throws IOException {
+      int type = TYPE_DATA;
+      int flags = 0;
+      if (outFinished) flags |= FLAG_END_STREAM;
+      out.writeInt((byteCount & 0xffff) << 16 | (type & 0xff) << 8 | (flags & 0xff));
+      out.writeInt(streamId & 0x7fffffff);
+      out.write(data, offset, byteCount);
+    }
+
+    @Override public synchronized void settings(Settings settings) throws IOException {
+      int type = TYPE_SETTINGS;
+      int length = settings.size() * 8;
+      int flags = 0;
+      int streamId = 0;
+      out.writeInt((length & 0xffff) << 16 | (type & 0xff) << 8 | (flags & 0xff));
+      out.writeInt(streamId & 0x7fffffff);
+      for (int i = 0; i < Settings.COUNT; i++) {
+        if (!settings.isSet(i)) continue;
+        out.writeInt(i & 0xffffff);
+        out.writeInt(settings.get(i));
+      }
+    }
+
+    @Override public synchronized void noop() throws IOException {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override public synchronized void ping(boolean reply, int payload1, int payload2)
+        throws IOException {
+      // TODO
+    }
+
+    @Override public synchronized void goAway(int lastGoodStreamId, ErrorCode errorCode)
+        throws IOException {
+      // TODO
+    }
+
+    @Override public synchronized void windowUpdate(int streamId, int deltaWindowSize)
+        throws IOException {
+      // TODO
+    }
+
+    @Override public void close() throws IOException {
+      out.close();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java b/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
old mode 100644
new mode 100755
index 875fff0..44d4ea2
--- a/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
+++ b/framework/src/com/squareup/okhttp/internal/spdy/IncomingStreamHandler.java
@@ -22,7 +22,7 @@ import java.io.IOException;
 public interface IncomingStreamHandler {
   IncomingStreamHandler REFUSE_INCOMING_STREAMS = new IncomingStreamHandler() {
     @Override public void receive(SpdyStream stream) throws IOException {
-      stream.close(SpdyStream.RST_REFUSED_STREAM);
+      stream.close(ErrorCode.REFUSED_STREAM);
     }
   };
 

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/NameValueBlockReader.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/NameValueBlockReader.java b/framework/src/com/squareup/okhttp/internal/spdy/NameValueBlockReader.java
new file mode 100755
index 0000000..b95d013
--- /dev/null
+++ b/framework/src/com/squareup/okhttp/internal/spdy/NameValueBlockReader.java
@@ -0,0 +1,123 @@
+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.util.ArrayList;
+import java.util.List;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+/**
+ * Reads a SPDY/3 Name/Value header block. This class is made complicated by the
+ * requirement that we're strict with which bytes we put in the compressed bytes
+ * buffer. We need to put all compressed bytes into that buffer -- but no other
+ * bytes.
+ */
+class NameValueBlockReader implements Closeable {
+  private final DataInputStream nameValueBlockIn;
+  private final FillableInflaterInputStream fillableInflaterInputStream;
+  private int compressedLimit;
+
+  NameValueBlockReader(final InputStream in) {
+    // Limit the inflater input stream to only those bytes in the Name/Value block. We cut the
+    // inflater off at its source because we can't predict the ratio of compressed bytes to
+    // uncompressed bytes.
+    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(Spdy3.DICTIONARY);
+          result = super.inflate(buffer, offset, count);
+        }
+        return result;
+      }
+    };
+
+    fillableInflaterInputStream = new FillableInflaterInputStream(throttleStream, inflater);
+    nameValueBlockIn = new DataInputStream(fillableInflaterInputStream);
+  }
+
+  /** Extend the inflater stream so we can eagerly fill the compressed bytes buffer if necessary. */
+  static class FillableInflaterInputStream extends InflaterInputStream {
+    public FillableInflaterInputStream(InputStream in, Inflater inf) {
+      super(in, inf);
+    }
+
+    @Override public void fill() throws IOException {
+      super.fill(); // This method is protected in the superclass.
+    }
+  }
+
+  public List<String> readNameValueBlock(int length) throws IOException {
+    this.compressedLimit += length;
+    try {
+      int numberOfPairs = nameValueBlockIn.readInt();
+      if (numberOfPairs < 0) {
+        throw new IOException("numberOfPairs < 0: " + numberOfPairs);
+      }
+      if (numberOfPairs > 1024) {
+        throw new IOException("numberOfPairs > 1024: " + numberOfPairs);
+      }
+      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 new IOException("name.length == 0");
+        entries.add(name);
+        entries.add(values);
+      }
+
+      doneReading();
+
+      return entries;
+    } catch (DataFormatException e) {
+      throw new IOException(e.getMessage());
+    }
+  }
+
+  private void doneReading() throws IOException {
+    if (compressedLimit == 0) return;
+
+    // Read any outstanding unread bytes. One side-effect of deflate compression is that sometimes
+    // there are bytes remaining in the stream after we've consumed all of the content.
+    fillableInflaterInputStream.fill();
+
+    if (compressedLimit != 0) {
+      throw new IOException("compressedLimit > 0: " + compressedLimit);
+    }
+  }
+
+  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");
+  }
+
+  @Override public void close() throws IOException {
+    nameValueBlockIn.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/185547ef/framework/src/com/squareup/okhttp/internal/spdy/Ping.java
----------------------------------------------------------------------
diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Ping.java b/framework/src/com/squareup/okhttp/internal/spdy/Ping.java
old mode 100644
new mode 100755


Mime
View raw message