Пример #1
0
  public void connect(int connectTimeout, int readTimeout, TunnelRequest tunnelRequest)
      throws IOException {
    if (connected) {
      throw new IllegalStateException("already connected");
    }
    connected = true;
    socket = (route.proxy.type() != Proxy.Type.HTTP) ? new Socket(route.proxy) : new Socket();
    Platform.get().connectSocket(socket, route.inetSocketAddress, connectTimeout);
    socket.setSoTimeout(readTimeout);
    in = socket.getInputStream();
    out = socket.getOutputStream();

    if (route.address.sslSocketFactory != null) {
      upgradeToTls(tunnelRequest);
    }

    // Use MTU-sized buffers to send fewer packets.
    int mtu = Platform.get().getMtu(socket);
    if (mtu < 1024) mtu = 1024;
    if (mtu > 8192) mtu = 8192;
    in = new BufferedInputStream(in, mtu);
    out = new BufferedOutputStream(out, mtu);
  }
Пример #2
0
    @Override
    public void configureTls(SSLSocket socket, String uriHost, String tlsVersion) {
      super.configureTls(socket, uriHost, tlsVersion);

      if (tlsVersion.equals("TLSv1") && openSslSocketClass.isInstance(socket)) {
        try {
          setUseSessionTickets.invoke(socket, true);
          setHostname.invoke(socket, uriHost);
        } catch (InvocationTargetException e) {
          throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
          throw new AssertionError(e);
        }
      }
    }
Пример #3
0
  public void connect(int connectTimeout, int readTimeout, TunnelRequest tunnelRequest)
      throws IOException {
    if (connected) throw new IllegalStateException("already connected");

    socket = (route.proxy.type() != Proxy.Type.HTTP) ? new Socket(route.proxy) : new Socket();
    Platform.get().connectSocket(socket, route.inetSocketAddress, connectTimeout);
    socket.setSoTimeout(readTimeout);

    if (route.address.sslSocketFactory != null) {
      upgradeToTls(tunnelRequest);
    } else {
      httpConnection = new HttpConnection(pool, this, socket);
    }
    connected = true;
  }
Пример #4
0
  public void connect(int connectTimeout, int readTimeout, TunnelRequest tunnelRequest)
      throws IOException {
    if (connected) throw new IllegalStateException("already connected");

    connected = true;
    socket = (route.proxy.type() != Proxy.Type.HTTP) ? new Socket(route.proxy) : new Socket();
    Platform.get().connectSocket(socket, route.inetSocketAddress, connectTimeout);
    socket.setSoTimeout(readTimeout);
    in = socket.getInputStream();
    out = socket.getOutputStream();

    if (route.address.sslSocketFactory != null) {
      upgradeToTls(tunnelRequest);
    } else {
      streamWrapper();
    }
  }
Пример #5
0
  /** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */
  private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException {
    Platform platform = Platform.get();

    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    if (requiresTunnel()) {
      makeTunnel(tunnelRequest);
    }

    // Create the wrapper over connected socket.
    socket =
        route.address.sslSocketFactory.createSocket(
            socket, route.address.uriHost, route.address.uriPort, true /* autoClose */);
    SSLSocket sslSocket = (SSLSocket) socket;
    if (route.modernTls) {
      platform.enableTlsExtensions(sslSocket, route.address.uriHost);
    } else {
      platform.supportTlsIntolerantServer(sslSocket);
    }

    boolean useNpn = route.modernTls && route.address.transports.contains("spdy/3");
    if (useNpn) {
      platform.setNpnProtocols(sslSocket, NPN_PROTOCOLS);
    }

    // Force handshake. This can throw!
    sslSocket.startHandshake();

    // Verify that the socket's certificates are acceptable for the target host.
    if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) {
      throw new IOException("Hostname '" + route.address.uriHost + "' was not verified");
    }

    out = sslSocket.getOutputStream();
    in = sslSocket.getInputStream();

    byte[] selectedProtocol;
    if (useNpn && (selectedProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
      if (Arrays.equals(selectedProtocol, SPDY3)) {
        sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream.
        spdyConnection =
            new SpdyConnection.Builder(route.address.getUriHost(), true, in, out).build();
        spdyConnection.sendConnectionHeader();
      } else if (!Arrays.equals(selectedProtocol, HTTP_11)) {
        throw new IOException(
            "Unexpected NPN transport " + new String(selectedProtocol, "ISO-8859-1"));
      }
    }
  }
Пример #6
0
  /**
   * @param requestHeaders the client's supplied request headers. This class creates a private copy
   *     that it can mutate.
   * @param connection the connection used for an intermediate response immediately prior to this
   *     request/response pair, such as a same-host redirect. This engine assumes ownership of the
   *     connection and must release it when it is unneeded.
   */
  public HttpEngine(
      OkHttpClient client,
      Policy policy,
      String method,
      RawHeaders requestHeaders,
      Connection connection,
      RetryableOutputStream requestBodyOut)
      throws IOException {
    this.client = client;
    this.policy = policy;
    this.method = method;
    this.connection = connection;
    this.requestBodyOut = requestBodyOut;

    try {
      uri = Platform.get().toUriLenient(policy.getURL());
    } catch (URISyntaxException e) {
      throw new IOException(e.getMessage());
    }

    this.requestHeaders = new RequestHeaders(uri, new RawHeaders(requestHeaders));
  }
  @Override
  public final void addRequestProperty(String field, String value) {
    if (connected) {
      throw new IllegalStateException("Cannot add request property after connection is made");
    }
    if (field == null) {
      throw new NullPointerException("field == null");
    }
    if (value == null) {
      // Silently ignore null header values for backwards compatibility with older
      // android versions as well as with other URLConnection implementations.
      //
      // Some implementations send a malformed HTTP header when faced with
      // such requests, we respect the spec and ignore the header.
      Platform.get().logW("Ignoring header " + field + " because its value was null.");
      return;
    }

    if ("X-Android-Transports".equals(field)) {
      setTransports(value, true /* append */);
    } else {
      requestHeaders.add(field, value);
    }
  }
Пример #8
0
 @Override
 public void log(String message) {
   Platform.get().logW(message);
 }
Пример #9
0
  /** Create an {@code SSLSocket} and perform the TLS handshake and certificate validation. */
  private void upgradeToTls(TunnelRequest tunnelRequest) throws IOException {
    Platform platform = Platform.get();

    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    if (requiresTunnel()) {
      makeTunnel(tunnelRequest);
    }

    // Create the wrapper over connected socket.
    socket =
        route.address.sslSocketFactory.createSocket(
            socket, route.address.uriHost, route.address.uriPort, true /* autoClose */);
    SSLSocket sslSocket = (SSLSocket) socket;
    if (route.modernTls) {
      platform.enableTlsExtensions(sslSocket, route.address.uriHost);
    } else {
      platform.supportTlsIntolerantServer(sslSocket);
    }

    boolean useNpn =
        route.modernTls
            && ( // Contains a spdy variant.
            route.address.protocols.contains(Protocol.HTTP_2)
                || route.address.protocols.contains(Protocol.SPDY_3));

    if (useNpn) {
      if (route.address.protocols.contains(Protocol.HTTP_2) // Contains both spdy variants.
          && route.address.protocols.contains(Protocol.SPDY_3)) {
        platform.setNpnProtocols(sslSocket, Protocol.HTTP2_SPDY3_AND_HTTP);
      } else if (route.address.protocols.contains(Protocol.HTTP_2)) {
        platform.setNpnProtocols(sslSocket, Protocol.HTTP2_AND_HTTP_11);
      } else {
        platform.setNpnProtocols(sslSocket, Protocol.SPDY3_AND_HTTP11);
      }
    }

    // Force handshake. This can throw!
    sslSocket.startHandshake();

    // Verify that the socket's certificates are acceptable for the target host.
    if (!route.address.hostnameVerifier.verify(route.address.uriHost, sslSocket.getSession())) {
      throw new IOException("Hostname '" + route.address.uriHost + "' was not verified");
    }

    out = sslSocket.getOutputStream();
    in = sslSocket.getInputStream();
    handshake = Handshake.get(sslSocket.getSession());
    streamWrapper();

    ByteString maybeProtocol;
    if (useNpn && (maybeProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
      Protocol selectedProtocol = Protocol.find(maybeProtocol); // Throws IOE on unknown.
      if (selectedProtocol.spdyVariant) {
        sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream.
        spdyConnection =
            new SpdyConnection.Builder(route.address.getUriHost(), true, in, out)
                .protocol(selectedProtocol)
                .build();
        spdyConnection.sendConnectionHeader();
      }
    }
  }
Пример #10
0
 private void assertResponseHeader(HttpURLConnection connection, String expected) {
   final String headerFieldPrefix = Platform.get().getPrefix();
   assertEquals(expected, connection.getHeaderField(headerFieldPrefix + "-Response-Source"));
 }