- Added realracing3-community.apk (71.57 MB) - Removed 32-bit support (armeabi-v7a) - Only includes arm64-v8a libraries - Decompiled source code included - Added README-community.md with analysis
434 lines
18 KiB
Java
434 lines
18 KiB
Java
package okhttp3.internal.connection;
|
|
|
|
import com.facebook.internal.security.CertificateUtil;
|
|
import java.io.IOException;
|
|
import java.net.ConnectException;
|
|
import java.net.Proxy;
|
|
import java.net.Socket;
|
|
import java.net.SocketTimeoutException;
|
|
import java.security.cert.X509Certificate;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.concurrent.TimeUnit;
|
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
|
import javax.net.ssl.SSLSession;
|
|
import javax.net.ssl.SSLSocket;
|
|
import okhttp3.Address;
|
|
import okhttp3.Call;
|
|
import okhttp3.CertificatePinner;
|
|
import okhttp3.Connection;
|
|
import okhttp3.ConnectionSpec;
|
|
import okhttp3.EventListener;
|
|
import okhttp3.Handshake;
|
|
import okhttp3.HttpUrl;
|
|
import okhttp3.Interceptor;
|
|
import okhttp3.OkHttpClient;
|
|
import okhttp3.Protocol;
|
|
import okhttp3.Request;
|
|
import okhttp3.Response;
|
|
import okhttp3.Route;
|
|
import okhttp3.internal.Internal;
|
|
import okhttp3.internal.Util;
|
|
import okhttp3.internal.Version;
|
|
import okhttp3.internal.http.ExchangeCodec;
|
|
import okhttp3.internal.http1.Http1ExchangeCodec;
|
|
import okhttp3.internal.http2.ConnectionShutdownException;
|
|
import okhttp3.internal.http2.ErrorCode;
|
|
import okhttp3.internal.http2.Http2Connection;
|
|
import okhttp3.internal.http2.Http2ExchangeCodec;
|
|
import okhttp3.internal.http2.Http2Stream;
|
|
import okhttp3.internal.http2.StreamResetException;
|
|
import okhttp3.internal.platform.Platform;
|
|
import okhttp3.internal.tls.OkHostnameVerifier;
|
|
import okio.BufferedSink;
|
|
import okio.BufferedSource;
|
|
import okio.Okio;
|
|
import okio.Timeout;
|
|
import org.apache.http.auth.AUTH;
|
|
import org.apache.http.protocol.HTTP;
|
|
|
|
/* loaded from: classes5.dex */
|
|
public final class RealConnection extends Http2Connection.Listener implements Connection {
|
|
public final RealConnectionPool connectionPool;
|
|
public Handshake handshake;
|
|
public Http2Connection http2Connection;
|
|
public boolean noNewExchanges;
|
|
public Protocol protocol;
|
|
public Socket rawSocket;
|
|
public int refusedStreamCount;
|
|
public final Route route;
|
|
public int routeFailureCount;
|
|
public BufferedSink sink;
|
|
public Socket socket;
|
|
public BufferedSource source;
|
|
public int successCount;
|
|
public int allocationLimit = 1;
|
|
public final List transmitters = new ArrayList();
|
|
public long idleAtNanos = Long.MAX_VALUE;
|
|
|
|
public Handshake handshake() {
|
|
return this.handshake;
|
|
}
|
|
|
|
public boolean isMultiplexed() {
|
|
return this.http2Connection != null;
|
|
}
|
|
|
|
public Route route() {
|
|
return this.route;
|
|
}
|
|
|
|
public Socket socket() {
|
|
return this.socket;
|
|
}
|
|
|
|
public RealConnection(RealConnectionPool realConnectionPool, Route route) {
|
|
this.connectionPool = realConnectionPool;
|
|
this.route = route;
|
|
}
|
|
|
|
public void noNewExchanges() {
|
|
synchronized (this.connectionPool) {
|
|
this.noNewExchanges = true;
|
|
}
|
|
}
|
|
|
|
/* JADX WARN: Removed duplicated region for block: B:32:0x00ed */
|
|
/* JADX WARN: Removed duplicated region for block: B:43:0x00fd A[ORIG_RETURN, RETURN] */
|
|
/* JADX WARN: Removed duplicated region for block: B:47:0x0131 */
|
|
/* JADX WARN: Removed duplicated region for block: B:49:0x013c */
|
|
/* JADX WARN: Removed duplicated region for block: B:54:0x0144 A[SYNTHETIC] */
|
|
/* JADX WARN: Removed duplicated region for block: B:56:0x0137 */
|
|
/*
|
|
Code decompiled incorrectly, please refer to instructions dump.
|
|
To view partially-correct add '--show-bad-code' argument
|
|
*/
|
|
public void connect(int r17, int r18, int r19, int r20, boolean r21, okhttp3.Call r22, okhttp3.EventListener r23) {
|
|
/*
|
|
Method dump skipped, instructions count: 346
|
|
To view this dump add '--comments-level debug' option
|
|
*/
|
|
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.connection.RealConnection.connect(int, int, int, int, boolean, okhttp3.Call, okhttp3.EventListener):void");
|
|
}
|
|
|
|
public final void connectTunnel(int i, int i2, int i3, Call call, EventListener eventListener) {
|
|
Request createTunnelRequest = createTunnelRequest();
|
|
HttpUrl url = createTunnelRequest.url();
|
|
for (int i4 = 0; i4 < 21; i4++) {
|
|
connectSocket(i, i2, call, eventListener);
|
|
createTunnelRequest = createTunnel(i2, i3, createTunnelRequest, url);
|
|
if (createTunnelRequest == null) {
|
|
return;
|
|
}
|
|
Util.closeQuietly(this.rawSocket);
|
|
this.rawSocket = null;
|
|
this.sink = null;
|
|
this.source = null;
|
|
eventListener.connectEnd(call, this.route.socketAddress(), this.route.proxy(), null);
|
|
}
|
|
}
|
|
|
|
public final void connectSocket(int i, int i2, Call call, EventListener eventListener) {
|
|
Socket createSocket;
|
|
Proxy proxy = this.route.proxy();
|
|
Address address = this.route.address();
|
|
if (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.HTTP) {
|
|
createSocket = address.socketFactory().createSocket();
|
|
} else {
|
|
createSocket = new Socket(proxy);
|
|
}
|
|
this.rawSocket = createSocket;
|
|
eventListener.connectStart(call, this.route.socketAddress(), proxy);
|
|
this.rawSocket.setSoTimeout(i2);
|
|
try {
|
|
Platform.get().connectSocket(this.rawSocket, this.route.socketAddress(), i);
|
|
try {
|
|
this.source = Okio.buffer(Okio.source(this.rawSocket));
|
|
this.sink = Okio.buffer(Okio.sink(this.rawSocket));
|
|
} catch (NullPointerException e) {
|
|
if ("throw with null exception".equals(e.getMessage())) {
|
|
throw new IOException(e);
|
|
}
|
|
}
|
|
} catch (ConnectException e2) {
|
|
ConnectException connectException = new ConnectException("Failed to connect to " + this.route.socketAddress());
|
|
connectException.initCause(e2);
|
|
throw connectException;
|
|
}
|
|
}
|
|
|
|
public final void establishProtocol(ConnectionSpecSelector connectionSpecSelector, int i, Call call, EventListener eventListener) {
|
|
if (this.route.address().sslSocketFactory() == null) {
|
|
List protocols = this.route.address().protocols();
|
|
Protocol protocol = Protocol.H2_PRIOR_KNOWLEDGE;
|
|
if (protocols.contains(protocol)) {
|
|
this.socket = this.rawSocket;
|
|
this.protocol = protocol;
|
|
startHttp2(i);
|
|
return;
|
|
} else {
|
|
this.socket = this.rawSocket;
|
|
this.protocol = Protocol.HTTP_1_1;
|
|
return;
|
|
}
|
|
}
|
|
eventListener.secureConnectStart(call);
|
|
connectTls(connectionSpecSelector);
|
|
eventListener.secureConnectEnd(call, this.handshake);
|
|
if (this.protocol == Protocol.HTTP_2) {
|
|
startHttp2(i);
|
|
}
|
|
}
|
|
|
|
public final void startHttp2(int i) {
|
|
this.socket.setSoTimeout(0);
|
|
Http2Connection build = new Http2Connection.Builder(true).socket(this.socket, this.route.address().url().host(), this.source, this.sink).listener(this).pingIntervalMillis(i).build();
|
|
this.http2Connection = build;
|
|
build.start();
|
|
}
|
|
|
|
public final void connectTls(ConnectionSpecSelector connectionSpecSelector) {
|
|
SSLSocket sSLSocket;
|
|
Protocol protocol;
|
|
Address address = this.route.address();
|
|
SSLSocket sSLSocket2 = null;
|
|
try {
|
|
try {
|
|
sSLSocket = (SSLSocket) address.sslSocketFactory().createSocket(this.rawSocket, address.url().host(), address.url().port(), true);
|
|
} catch (AssertionError e) {
|
|
e = e;
|
|
}
|
|
} catch (Throwable th) {
|
|
th = th;
|
|
}
|
|
try {
|
|
ConnectionSpec configureSecureSocket = connectionSpecSelector.configureSecureSocket(sSLSocket);
|
|
if (configureSecureSocket.supportsTlsExtensions()) {
|
|
Platform.get().configureTlsExtensions(sSLSocket, address.url().host(), address.protocols());
|
|
}
|
|
sSLSocket.startHandshake();
|
|
SSLSession session = sSLSocket.getSession();
|
|
Handshake handshake = Handshake.get(session);
|
|
if (!address.hostnameVerifier().verify(address.url().host(), session)) {
|
|
List peerCertificates = handshake.peerCertificates();
|
|
if (!peerCertificates.isEmpty()) {
|
|
X509Certificate x509Certificate = (X509Certificate) peerCertificates.get(0);
|
|
throw new SSLPeerUnverifiedException("Hostname " + address.url().host() + " not verified:\n certificate: " + CertificatePinner.pin(x509Certificate) + "\n DN: " + x509Certificate.getSubjectDN().getName() + "\n subjectAltNames: " + OkHostnameVerifier.allSubjectAltNames(x509Certificate));
|
|
}
|
|
throw new SSLPeerUnverifiedException("Hostname " + address.url().host() + " not verified (no certificates)");
|
|
}
|
|
address.certificatePinner().check(address.url().host(), handshake.peerCertificates());
|
|
String selectedProtocol = configureSecureSocket.supportsTlsExtensions() ? Platform.get().getSelectedProtocol(sSLSocket) : null;
|
|
this.socket = sSLSocket;
|
|
this.source = Okio.buffer(Okio.source(sSLSocket));
|
|
this.sink = Okio.buffer(Okio.sink(this.socket));
|
|
this.handshake = handshake;
|
|
if (selectedProtocol != null) {
|
|
protocol = Protocol.get(selectedProtocol);
|
|
} else {
|
|
protocol = Protocol.HTTP_1_1;
|
|
}
|
|
this.protocol = protocol;
|
|
Platform.get().afterHandshake(sSLSocket);
|
|
} catch (AssertionError e2) {
|
|
e = e2;
|
|
if (!Util.isAndroidGetsocknameError(e)) {
|
|
throw e;
|
|
}
|
|
throw new IOException(e);
|
|
} catch (Throwable th2) {
|
|
th = th2;
|
|
sSLSocket2 = sSLSocket;
|
|
if (sSLSocket2 != null) {
|
|
Platform.get().afterHandshake(sSLSocket2);
|
|
}
|
|
Util.closeQuietly((Socket) sSLSocket2);
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public final Request createTunnel(int i, int i2, Request request, HttpUrl httpUrl) {
|
|
String str = "CONNECT " + Util.hostHeader(httpUrl, true) + " HTTP/1.1";
|
|
while (true) {
|
|
Http1ExchangeCodec http1ExchangeCodec = new Http1ExchangeCodec(null, null, this.source, this.sink);
|
|
TimeUnit timeUnit = TimeUnit.MILLISECONDS;
|
|
this.source.timeout().timeout(i, timeUnit);
|
|
this.sink.timeout().timeout(i2, timeUnit);
|
|
http1ExchangeCodec.writeRequest(request.headers(), str);
|
|
http1ExchangeCodec.finishRequest();
|
|
Response build = http1ExchangeCodec.readResponseHeaders(false).request(request).build();
|
|
http1ExchangeCodec.skipConnectBody(build);
|
|
int code = build.code();
|
|
if (code == 200) {
|
|
if (this.source.getBuffer().exhausted() && this.sink.buffer().exhausted()) {
|
|
return null;
|
|
}
|
|
throw new IOException("TLS tunnel buffered too many bytes!");
|
|
}
|
|
if (code == 407) {
|
|
Request authenticate = this.route.address().proxyAuthenticator().authenticate(this.route, build);
|
|
if (authenticate == null) {
|
|
throw new IOException("Failed to authenticate with proxy");
|
|
}
|
|
if ("close".equalsIgnoreCase(build.header(HTTP.CONN_DIRECTIVE))) {
|
|
return authenticate;
|
|
}
|
|
request = authenticate;
|
|
} else {
|
|
throw new IOException("Unexpected response code for CONNECT: " + build.code());
|
|
}
|
|
}
|
|
}
|
|
|
|
public final Request createTunnelRequest() {
|
|
Request build = new Request.Builder().url(this.route.address().url()).method("CONNECT", null).header(HTTP.TARGET_HOST, Util.hostHeader(this.route.address().url(), true)).header("Proxy-Connection", HTTP.CONN_KEEP_ALIVE).header("User-Agent", Version.userAgent()).build();
|
|
Request authenticate = this.route.address().proxyAuthenticator().authenticate(this.route, new Response.Builder().request(build).protocol(Protocol.HTTP_1_1).code(407).message("Preemptive Authenticate").body(Util.EMPTY_RESPONSE).sentRequestAtMillis(-1L).receivedResponseAtMillis(-1L).header(AUTH.PROXY_AUTH, "OkHttp-Preemptive").build());
|
|
return authenticate != null ? authenticate : build;
|
|
}
|
|
|
|
public boolean isEligible(Address address, List list) {
|
|
if (this.transmitters.size() >= this.allocationLimit || this.noNewExchanges || !Internal.instance.equalsNonHost(this.route.address(), address)) {
|
|
return false;
|
|
}
|
|
if (address.url().host().equals(route().address().url().host())) {
|
|
return true;
|
|
}
|
|
if (this.http2Connection == null || list == null || !routeMatchesAny(list) || address.hostnameVerifier() != OkHostnameVerifier.INSTANCE || !supportsUrl(address.url())) {
|
|
return false;
|
|
}
|
|
try {
|
|
address.certificatePinner().check(address.url().host(), handshake().peerCertificates());
|
|
return true;
|
|
} catch (SSLPeerUnverifiedException unused) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public final boolean routeMatchesAny(List list) {
|
|
int size = list.size();
|
|
for (int i = 0; i < size; i++) {
|
|
Route route = (Route) list.get(i);
|
|
Proxy.Type type = route.proxy().type();
|
|
Proxy.Type type2 = Proxy.Type.DIRECT;
|
|
if (type == type2 && this.route.proxy().type() == type2 && this.route.socketAddress().equals(route.socketAddress())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean supportsUrl(HttpUrl httpUrl) {
|
|
if (httpUrl.port() != this.route.address().url().port()) {
|
|
return false;
|
|
}
|
|
if (httpUrl.host().equals(this.route.address().url().host())) {
|
|
return true;
|
|
}
|
|
return this.handshake != null && OkHostnameVerifier.INSTANCE.verify(httpUrl.host(), (X509Certificate) this.handshake.peerCertificates().get(0));
|
|
}
|
|
|
|
public ExchangeCodec newCodec(OkHttpClient okHttpClient, Interceptor.Chain chain) {
|
|
if (this.http2Connection != null) {
|
|
return new Http2ExchangeCodec(okHttpClient, this, chain, this.http2Connection);
|
|
}
|
|
this.socket.setSoTimeout(chain.readTimeoutMillis());
|
|
Timeout timeout = this.source.timeout();
|
|
long readTimeoutMillis = chain.readTimeoutMillis();
|
|
TimeUnit timeUnit = TimeUnit.MILLISECONDS;
|
|
timeout.timeout(readTimeoutMillis, timeUnit);
|
|
this.sink.timeout().timeout(chain.writeTimeoutMillis(), timeUnit);
|
|
return new Http1ExchangeCodec(okHttpClient, this, this.source, this.sink);
|
|
}
|
|
|
|
public void cancel() {
|
|
Util.closeQuietly(this.rawSocket);
|
|
}
|
|
|
|
public boolean isHealthy(boolean z) {
|
|
if (this.socket.isClosed() || this.socket.isInputShutdown() || this.socket.isOutputShutdown()) {
|
|
return false;
|
|
}
|
|
Http2Connection http2Connection = this.http2Connection;
|
|
if (http2Connection != null) {
|
|
return http2Connection.isHealthy(System.nanoTime());
|
|
}
|
|
if (z) {
|
|
try {
|
|
int soTimeout = this.socket.getSoTimeout();
|
|
try {
|
|
this.socket.setSoTimeout(1);
|
|
return !this.source.exhausted();
|
|
} finally {
|
|
this.socket.setSoTimeout(soTimeout);
|
|
}
|
|
} catch (SocketTimeoutException unused) {
|
|
} catch (IOException unused2) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override // okhttp3.internal.http2.Http2Connection.Listener
|
|
public void onStream(Http2Stream http2Stream) {
|
|
http2Stream.close(ErrorCode.REFUSED_STREAM, null);
|
|
}
|
|
|
|
@Override // okhttp3.internal.http2.Http2Connection.Listener
|
|
public void onSettings(Http2Connection http2Connection) {
|
|
synchronized (this.connectionPool) {
|
|
this.allocationLimit = http2Connection.maxConcurrentStreams();
|
|
}
|
|
}
|
|
|
|
public void trackFailure(IOException iOException) {
|
|
synchronized (this.connectionPool) {
|
|
try {
|
|
if (iOException instanceof StreamResetException) {
|
|
ErrorCode errorCode = ((StreamResetException) iOException).errorCode;
|
|
if (errorCode == ErrorCode.REFUSED_STREAM) {
|
|
int i = this.refusedStreamCount + 1;
|
|
this.refusedStreamCount = i;
|
|
if (i > 1) {
|
|
this.noNewExchanges = true;
|
|
this.routeFailureCount++;
|
|
}
|
|
} else if (errorCode != ErrorCode.CANCEL) {
|
|
this.noNewExchanges = true;
|
|
this.routeFailureCount++;
|
|
}
|
|
} else if (!isMultiplexed() || (iOException instanceof ConnectionShutdownException)) {
|
|
this.noNewExchanges = true;
|
|
if (this.successCount == 0) {
|
|
if (iOException != null) {
|
|
this.connectionPool.connectFailed(this.route, iOException);
|
|
}
|
|
this.routeFailureCount++;
|
|
}
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
}
|
|
|
|
public String toString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append("Connection{");
|
|
sb.append(this.route.address().url().host());
|
|
sb.append(CertificateUtil.DELIMITER);
|
|
sb.append(this.route.address().url().port());
|
|
sb.append(", proxy=");
|
|
sb.append(this.route.proxy());
|
|
sb.append(" hostAddress=");
|
|
sb.append(this.route.socketAddress());
|
|
sb.append(" cipherSuite=");
|
|
Handshake handshake = this.handshake;
|
|
sb.append(handshake != null ? handshake.cipherSuite() : "none");
|
|
sb.append(" protocol=");
|
|
sb.append(this.protocol);
|
|
sb.append('}');
|
|
return sb.toString();
|
|
}
|
|
}
|