Initial commit
This commit is contained in:
54
sources/okhttp3/internal/Internal.java
Normal file
54
sources/okhttp3/internal/Internal.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package okhttp3.internal;
|
||||
|
||||
import java.net.Socket;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import okhttp3.Address;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.Route;
|
||||
import okhttp3.internal.cache.InternalCache;
|
||||
import okhttp3.internal.connection.RealConnection;
|
||||
import okhttp3.internal.connection.RouteDatabase;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public abstract class Internal {
|
||||
public static Internal instance;
|
||||
|
||||
public static void initializeInstanceForTests() {
|
||||
new OkHttpClient();
|
||||
}
|
||||
|
||||
public abstract void addLenient(Headers.Builder builder, String str);
|
||||
|
||||
public abstract void addLenient(Headers.Builder builder, String str, String str2);
|
||||
|
||||
public abstract void apply(ConnectionSpec connectionSpec, SSLSocket sSLSocket, boolean z);
|
||||
|
||||
public abstract int code(Response.Builder builder);
|
||||
|
||||
public abstract boolean connectionBecameIdle(ConnectionPool connectionPool, RealConnection realConnection);
|
||||
|
||||
public abstract Socket deduplicate(ConnectionPool connectionPool, Address address, StreamAllocation streamAllocation);
|
||||
|
||||
public abstract boolean equalsNonHost(Address address, Address address2);
|
||||
|
||||
public abstract RealConnection get(ConnectionPool connectionPool, Address address, StreamAllocation streamAllocation, Route route);
|
||||
|
||||
public abstract boolean isInvalidHttpUrlHost(IllegalArgumentException illegalArgumentException);
|
||||
|
||||
public abstract Call newWebSocketCall(OkHttpClient okHttpClient, Request request);
|
||||
|
||||
public abstract void put(ConnectionPool connectionPool, RealConnection realConnection);
|
||||
|
||||
public abstract RouteDatabase routeDatabase(ConnectionPool connectionPool);
|
||||
|
||||
public abstract void setCache(OkHttpClient.Builder builder, InternalCache internalCache);
|
||||
|
||||
public abstract StreamAllocation streamAllocation(Call call);
|
||||
}
|
||||
23
sources/okhttp3/internal/NamedRunnable.java
Normal file
23
sources/okhttp3/internal/NamedRunnable.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package okhttp3.internal;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public abstract class NamedRunnable implements Runnable {
|
||||
protected final String name;
|
||||
|
||||
public NamedRunnable(String str, Object... objArr) {
|
||||
this.name = Util.format(str, objArr);
|
||||
}
|
||||
|
||||
protected abstract void execute();
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public final void run() {
|
||||
String name = Thread.currentThread().getName();
|
||||
Thread.currentThread().setName(this.name);
|
||||
try {
|
||||
execute();
|
||||
} finally {
|
||||
Thread.currentThread().setName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
636
sources/okhttp3/internal/Util.java
Normal file
636
sources/okhttp3/internal/Util.java
Normal file
@@ -0,0 +1,636 @@
|
||||
package okhttp3.internal;
|
||||
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.IDN;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Util {
|
||||
private static final Pattern VERIFY_AS_IP_ADDRESS;
|
||||
private static final Method addSuppressedExceptionMethod;
|
||||
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
public static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
public static final ResponseBody EMPTY_RESPONSE = ResponseBody.create((MediaType) null, EMPTY_BYTE_ARRAY);
|
||||
public static final RequestBody EMPTY_REQUEST = RequestBody.create((MediaType) null, EMPTY_BYTE_ARRAY);
|
||||
private static final ByteString UTF_8_BOM = ByteString.decodeHex("efbbbf");
|
||||
private static final ByteString UTF_16_BE_BOM = ByteString.decodeHex("feff");
|
||||
private static final ByteString UTF_16_LE_BOM = ByteString.decodeHex("fffe");
|
||||
private static final ByteString UTF_32_BE_BOM = ByteString.decodeHex("0000ffff");
|
||||
private static final ByteString UTF_32_LE_BOM = ByteString.decodeHex("ffff0000");
|
||||
public static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||
private static final Charset UTF_16_BE = Charset.forName("UTF-16BE");
|
||||
private static final Charset UTF_16_LE = Charset.forName("UTF-16LE");
|
||||
private static final Charset UTF_32_BE = Charset.forName("UTF-32BE");
|
||||
private static final Charset UTF_32_LE = Charset.forName("UTF-32LE");
|
||||
public static final TimeZone UTC = TimeZone.getTimeZone("GMT");
|
||||
public static final Comparator<String> NATURAL_ORDER = new Comparator<String>() { // from class: okhttp3.internal.Util.1
|
||||
@Override // java.util.Comparator
|
||||
public int compare(String str, String str2) {
|
||||
return str.compareTo(str2);
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
Method method = null;
|
||||
try {
|
||||
method = Throwable.class.getDeclaredMethod("addSuppressed", Throwable.class);
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
addSuppressedExceptionMethod = method;
|
||||
VERIFY_AS_IP_ADDRESS = Pattern.compile("([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");
|
||||
}
|
||||
|
||||
private Util() {
|
||||
}
|
||||
|
||||
public static void addSuppressedIfPossible(Throwable th, Throwable th2) {
|
||||
Method method = addSuppressedExceptionMethod;
|
||||
if (method != null) {
|
||||
try {
|
||||
method.invoke(th, th2);
|
||||
} catch (IllegalAccessException | InvocationTargetException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AssertionError assertionError(String str, Exception exc) {
|
||||
AssertionError assertionError = new AssertionError(str);
|
||||
try {
|
||||
assertionError.initCause(exc);
|
||||
} catch (IllegalStateException unused) {
|
||||
}
|
||||
return assertionError;
|
||||
}
|
||||
|
||||
public static Charset bomAwareCharset(BufferedSource bufferedSource, Charset charset) throws IOException {
|
||||
if (bufferedSource.rangeEquals(0L, UTF_8_BOM)) {
|
||||
bufferedSource.skip(UTF_8_BOM.size());
|
||||
return UTF_8;
|
||||
}
|
||||
if (bufferedSource.rangeEquals(0L, UTF_16_BE_BOM)) {
|
||||
bufferedSource.skip(UTF_16_BE_BOM.size());
|
||||
return UTF_16_BE;
|
||||
}
|
||||
if (bufferedSource.rangeEquals(0L, UTF_16_LE_BOM)) {
|
||||
bufferedSource.skip(UTF_16_LE_BOM.size());
|
||||
return UTF_16_LE;
|
||||
}
|
||||
if (bufferedSource.rangeEquals(0L, UTF_32_BE_BOM)) {
|
||||
bufferedSource.skip(UTF_32_BE_BOM.size());
|
||||
return UTF_32_BE;
|
||||
}
|
||||
if (!bufferedSource.rangeEquals(0L, UTF_32_LE_BOM)) {
|
||||
return charset;
|
||||
}
|
||||
bufferedSource.skip(UTF_32_LE_BOM.size());
|
||||
return UTF_32_LE;
|
||||
}
|
||||
|
||||
public static String canonicalizeHost(String str) {
|
||||
if (!str.contains(":")) {
|
||||
try {
|
||||
String lowerCase = IDN.toASCII(str).toLowerCase(Locale.US);
|
||||
if (lowerCase.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (containsInvalidHostnameAsciiCodes(lowerCase)) {
|
||||
return null;
|
||||
}
|
||||
return lowerCase;
|
||||
} catch (IllegalArgumentException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
InetAddress decodeIpv6 = (str.startsWith("[") && str.endsWith("]")) ? decodeIpv6(str, 1, str.length() - 1) : decodeIpv6(str, 0, str.length());
|
||||
if (decodeIpv6 == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] address = decodeIpv6.getAddress();
|
||||
if (address.length == 16) {
|
||||
return inet6AddressToAscii(address);
|
||||
}
|
||||
throw new AssertionError("Invalid IPv6 address: '" + str + "'");
|
||||
}
|
||||
|
||||
public static int checkDuration(String str, long j, TimeUnit timeUnit) {
|
||||
if (j < 0) {
|
||||
throw new IllegalArgumentException(str + " < 0");
|
||||
}
|
||||
if (timeUnit == null) {
|
||||
throw new NullPointerException("unit == null");
|
||||
}
|
||||
long millis = timeUnit.toMillis(j);
|
||||
if (millis > 2147483647L) {
|
||||
throw new IllegalArgumentException(str + " too large.");
|
||||
}
|
||||
if (millis != 0 || j <= 0) {
|
||||
return (int) millis;
|
||||
}
|
||||
throw new IllegalArgumentException(str + " too small.");
|
||||
}
|
||||
|
||||
public static void checkOffsetAndCount(long j, long j2, long j3) {
|
||||
if ((j2 | j3) < 0 || j2 > j || j - j2 < j3) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] concat(String[] strArr, String str) {
|
||||
String[] strArr2 = new String[strArr.length + 1];
|
||||
System.arraycopy(strArr, 0, strArr2, 0, strArr.length);
|
||||
strArr2[strArr2.length - 1] = str;
|
||||
return strArr2;
|
||||
}
|
||||
|
||||
private static boolean containsInvalidHostnameAsciiCodes(String str) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char charAt = str.charAt(i);
|
||||
if (charAt <= 31 || charAt >= 127 || " #%/:?@[\\]".indexOf(charAt) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int decodeHexDigit(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
char c2 = 'a';
|
||||
if (c < 'a' || c > 'f') {
|
||||
c2 = 'A';
|
||||
if (c < 'A' || c > 'F') {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (c - c2) + 10;
|
||||
}
|
||||
|
||||
private static boolean decodeIpv4Suffix(String str, int i, int i2, byte[] bArr, int i3) {
|
||||
int i4 = i3;
|
||||
while (i < i2) {
|
||||
if (i4 == bArr.length) {
|
||||
return false;
|
||||
}
|
||||
if (i4 != i3) {
|
||||
if (str.charAt(i) != '.') {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int i5 = i;
|
||||
int i6 = 0;
|
||||
while (i5 < i2) {
|
||||
char charAt = str.charAt(i5);
|
||||
if (charAt < '0' || charAt > '9') {
|
||||
break;
|
||||
}
|
||||
if ((i6 == 0 && i != i5) || (i6 = ((i6 * 10) + charAt) - 48) > 255) {
|
||||
return false;
|
||||
}
|
||||
i5++;
|
||||
}
|
||||
if (i5 - i == 0) {
|
||||
return false;
|
||||
}
|
||||
bArr[i4] = (byte) i6;
|
||||
i4++;
|
||||
i = i5;
|
||||
}
|
||||
return i4 == i3 + 4;
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:26:0x007a, code lost:
|
||||
|
||||
return null;
|
||||
*/
|
||||
/* JADX WARN: Removed duplicated region for block: B:16:0x0050 */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
private static java.net.InetAddress decodeIpv6(java.lang.String r10, int r11, int r12) {
|
||||
/*
|
||||
r0 = 16
|
||||
byte[] r0 = new byte[r0]
|
||||
r1 = -1
|
||||
r2 = 0
|
||||
r3 = 0
|
||||
r4 = -1
|
||||
r5 = -1
|
||||
L9:
|
||||
r6 = 0
|
||||
if (r11 >= r12) goto L7b
|
||||
int r7 = r0.length
|
||||
if (r3 != r7) goto L10
|
||||
return r6
|
||||
L10:
|
||||
int r7 = r11 + 2
|
||||
if (r7 > r12) goto L28
|
||||
r8 = 2
|
||||
java.lang.String r9 = "::"
|
||||
boolean r8 = r10.regionMatches(r11, r9, r2, r8)
|
||||
if (r8 == 0) goto L28
|
||||
if (r4 == r1) goto L20
|
||||
return r6
|
||||
L20:
|
||||
int r3 = r3 + 2
|
||||
r4 = r3
|
||||
if (r7 != r12) goto L26
|
||||
goto L7b
|
||||
L26:
|
||||
r5 = r7
|
||||
goto L4c
|
||||
L28:
|
||||
if (r3 == 0) goto L4b
|
||||
r7 = 1
|
||||
java.lang.String r8 = ":"
|
||||
boolean r8 = r10.regionMatches(r11, r8, r2, r7)
|
||||
if (r8 == 0) goto L36
|
||||
int r11 = r11 + 1
|
||||
goto L4b
|
||||
L36:
|
||||
java.lang.String r8 = "."
|
||||
boolean r11 = r10.regionMatches(r11, r8, r2, r7)
|
||||
if (r11 == 0) goto L4a
|
||||
int r11 = r3 + (-2)
|
||||
boolean r10 = decodeIpv4Suffix(r10, r5, r12, r0, r11)
|
||||
if (r10 != 0) goto L47
|
||||
return r6
|
||||
L47:
|
||||
int r3 = r3 + 2
|
||||
goto L7b
|
||||
L4a:
|
||||
return r6
|
||||
L4b:
|
||||
r5 = r11
|
||||
L4c:
|
||||
r11 = r5
|
||||
r7 = 0
|
||||
L4e:
|
||||
if (r11 >= r12) goto L61
|
||||
char r8 = r10.charAt(r11)
|
||||
int r8 = decodeHexDigit(r8)
|
||||
if (r8 != r1) goto L5b
|
||||
goto L61
|
||||
L5b:
|
||||
int r7 = r7 << 4
|
||||
int r7 = r7 + r8
|
||||
int r11 = r11 + 1
|
||||
goto L4e
|
||||
L61:
|
||||
int r8 = r11 - r5
|
||||
if (r8 == 0) goto L7a
|
||||
r9 = 4
|
||||
if (r8 <= r9) goto L69
|
||||
goto L7a
|
||||
L69:
|
||||
int r6 = r3 + 1
|
||||
int r8 = r7 >>> 8
|
||||
r8 = r8 & 255(0xff, float:3.57E-43)
|
||||
byte r8 = (byte) r8
|
||||
r0[r3] = r8
|
||||
int r3 = r6 + 1
|
||||
r7 = r7 & 255(0xff, float:3.57E-43)
|
||||
byte r7 = (byte) r7
|
||||
r0[r6] = r7
|
||||
goto L9
|
||||
L7a:
|
||||
return r6
|
||||
L7b:
|
||||
int r10 = r0.length
|
||||
if (r3 == r10) goto L8e
|
||||
if (r4 != r1) goto L81
|
||||
return r6
|
||||
L81:
|
||||
int r10 = r0.length
|
||||
int r11 = r3 - r4
|
||||
int r10 = r10 - r11
|
||||
java.lang.System.arraycopy(r0, r4, r0, r10, r11)
|
||||
int r10 = r0.length
|
||||
int r10 = r10 - r3
|
||||
int r10 = r10 + r4
|
||||
java.util.Arrays.fill(r0, r4, r10, r2)
|
||||
L8e:
|
||||
java.net.InetAddress r10 = java.net.InetAddress.getByAddress(r0) // Catch: java.net.UnknownHostException -> L93
|
||||
return r10
|
||||
L93:
|
||||
java.lang.AssertionError r10 = new java.lang.AssertionError
|
||||
r10.<init>()
|
||||
throw r10
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.Util.decodeIpv6(java.lang.String, int, int):java.net.InetAddress");
|
||||
}
|
||||
|
||||
public static int delimiterOffset(String str, int i, int i2, String str2) {
|
||||
while (i < i2) {
|
||||
if (str2.indexOf(str.charAt(i)) != -1) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i2;
|
||||
}
|
||||
|
||||
public static boolean discard(Source source, int i, TimeUnit timeUnit) {
|
||||
try {
|
||||
return skipAll(source, i, timeUnit);
|
||||
} catch (IOException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean equal(Object obj, Object obj2) {
|
||||
return obj == obj2 || (obj != null && obj.equals(obj2));
|
||||
}
|
||||
|
||||
public static String format(String str, Object... objArr) {
|
||||
return String.format(Locale.US, str, objArr);
|
||||
}
|
||||
|
||||
public static String hostHeader(HttpUrl httpUrl, boolean z) {
|
||||
String host;
|
||||
if (httpUrl.host().contains(":")) {
|
||||
host = "[" + httpUrl.host() + "]";
|
||||
} else {
|
||||
host = httpUrl.host();
|
||||
}
|
||||
if (!z && httpUrl.port() == HttpUrl.defaultPort(httpUrl.scheme())) {
|
||||
return host;
|
||||
}
|
||||
return host + ":" + httpUrl.port();
|
||||
}
|
||||
|
||||
public static <T> List<T> immutableList(List<T> list) {
|
||||
return Collections.unmodifiableList(new ArrayList(list));
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> immutableMap(Map<K, V> map) {
|
||||
return map.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(new LinkedHashMap(map));
|
||||
}
|
||||
|
||||
public static int indexOf(Comparator<String> comparator, String[] strArr, String str) {
|
||||
int length = strArr.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (comparator.compare(strArr[i], str) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int indexOfControlOrNonAscii(String str) {
|
||||
int length = str.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char charAt = str.charAt(i);
|
||||
if (charAt <= 31 || charAt >= 127) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String inet6AddressToAscii(byte[] bArr) {
|
||||
int i = 0;
|
||||
int i2 = 0;
|
||||
int i3 = -1;
|
||||
int i4 = 0;
|
||||
while (i2 < bArr.length) {
|
||||
int i5 = i2;
|
||||
while (i5 < 16 && bArr[i5] == 0 && bArr[i5 + 1] == 0) {
|
||||
i5 += 2;
|
||||
}
|
||||
int i6 = i5 - i2;
|
||||
if (i6 > i4 && i6 >= 4) {
|
||||
i3 = i2;
|
||||
i4 = i6;
|
||||
}
|
||||
i2 = i5 + 2;
|
||||
}
|
||||
Buffer buffer = new Buffer();
|
||||
while (i < bArr.length) {
|
||||
if (i == i3) {
|
||||
buffer.writeByte(58);
|
||||
i += i4;
|
||||
if (i == 16) {
|
||||
buffer.writeByte(58);
|
||||
}
|
||||
} else {
|
||||
if (i > 0) {
|
||||
buffer.writeByte(58);
|
||||
}
|
||||
buffer.writeHexadecimalUnsignedLong(((bArr[i] & 255) << 8) | (bArr[i + 1] & 255));
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return buffer.readUtf8();
|
||||
}
|
||||
|
||||
public static String[] intersect(Comparator<? super String> comparator, String[] strArr, String[] strArr2) {
|
||||
ArrayList arrayList = new ArrayList();
|
||||
for (String str : strArr) {
|
||||
int length = strArr2.length;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if (i >= length) {
|
||||
break;
|
||||
}
|
||||
if (comparator.compare(str, strArr2[i]) == 0) {
|
||||
arrayList.add(str);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return (String[]) arrayList.toArray(new String[arrayList.size()]);
|
||||
}
|
||||
|
||||
public static boolean isAndroidGetsocknameError(AssertionError assertionError) {
|
||||
return (assertionError.getCause() == null || assertionError.getMessage() == null || !assertionError.getMessage().contains("getsockname failed")) ? false : true;
|
||||
}
|
||||
|
||||
public static boolean nonEmptyIntersection(Comparator<String> comparator, String[] strArr, String[] strArr2) {
|
||||
if (strArr != null && strArr2 != null && strArr.length != 0 && strArr2.length != 0) {
|
||||
for (String str : strArr) {
|
||||
for (String str2 : strArr2) {
|
||||
if (comparator.compare(str, str2) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static X509TrustManager platformTrustManager() {
|
||||
try {
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
if (trustManagers.length == 1 && (trustManagers[0] instanceof X509TrustManager)) {
|
||||
return (X509TrustManager) trustManagers[0];
|
||||
}
|
||||
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw assertionError("No System TLS", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean skipAll(Source source, int i, TimeUnit timeUnit) throws IOException {
|
||||
long nanoTime = System.nanoTime();
|
||||
long deadlineNanoTime = source.timeout().hasDeadline() ? source.timeout().deadlineNanoTime() - nanoTime : Long.MAX_VALUE;
|
||||
source.timeout().deadlineNanoTime(Math.min(deadlineNanoTime, timeUnit.toNanos(i)) + nanoTime);
|
||||
try {
|
||||
Buffer buffer = new Buffer();
|
||||
while (source.read(buffer, PlaybackStateCompat.ACTION_PLAY_FROM_URI) != -1) {
|
||||
buffer.clear();
|
||||
}
|
||||
if (deadlineNanoTime == Long.MAX_VALUE) {
|
||||
source.timeout().clearDeadline();
|
||||
} else {
|
||||
source.timeout().deadlineNanoTime(nanoTime + deadlineNanoTime);
|
||||
}
|
||||
return true;
|
||||
} catch (InterruptedIOException unused) {
|
||||
if (deadlineNanoTime == Long.MAX_VALUE) {
|
||||
source.timeout().clearDeadline();
|
||||
} else {
|
||||
source.timeout().deadlineNanoTime(nanoTime + deadlineNanoTime);
|
||||
}
|
||||
return false;
|
||||
} catch (Throwable th) {
|
||||
if (deadlineNanoTime == Long.MAX_VALUE) {
|
||||
source.timeout().clearDeadline();
|
||||
} else {
|
||||
source.timeout().deadlineNanoTime(nanoTime + deadlineNanoTime);
|
||||
}
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
public static int skipLeadingAsciiWhitespace(String str, int i, int i2) {
|
||||
while (i < i2) {
|
||||
char charAt = str.charAt(i);
|
||||
if (charAt != '\t' && charAt != '\n' && charAt != '\f' && charAt != '\r' && charAt != ' ') {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i2;
|
||||
}
|
||||
|
||||
public static int skipTrailingAsciiWhitespace(String str, int i, int i2) {
|
||||
for (int i3 = i2 - 1; i3 >= i; i3--) {
|
||||
char charAt = str.charAt(i3);
|
||||
if (charAt != '\t' && charAt != '\n' && charAt != '\f' && charAt != '\r' && charAt != ' ') {
|
||||
return i3 + 1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static ThreadFactory threadFactory(final String str, final boolean z) {
|
||||
return new ThreadFactory() { // from class: okhttp3.internal.Util.2
|
||||
@Override // java.util.concurrent.ThreadFactory
|
||||
public Thread newThread(Runnable runnable) {
|
||||
Thread thread = new Thread(runnable, str);
|
||||
thread.setDaemon(z);
|
||||
return thread;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static String trimSubstring(String str, int i, int i2) {
|
||||
int skipLeadingAsciiWhitespace = skipLeadingAsciiWhitespace(str, i, i2);
|
||||
return str.substring(skipLeadingAsciiWhitespace, skipTrailingAsciiWhitespace(str, skipLeadingAsciiWhitespace, i2));
|
||||
}
|
||||
|
||||
public static boolean verifyAsIpAddress(String str) {
|
||||
return VERIFY_AS_IP_ADDRESS.matcher(str).matches();
|
||||
}
|
||||
|
||||
public static int delimiterOffset(String str, int i, int i2, char c) {
|
||||
while (i < i2) {
|
||||
if (str.charAt(i) == c) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i2;
|
||||
}
|
||||
|
||||
public static <T> List<T> immutableList(T... tArr) {
|
||||
return Collections.unmodifiableList(Arrays.asList((Object[]) tArr.clone()));
|
||||
}
|
||||
|
||||
public static void closeQuietly(Socket socket) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (AssertionError e) {
|
||||
if (!isAndroidGetsocknameError(e)) {
|
||||
throw e;
|
||||
}
|
||||
} catch (RuntimeException e2) {
|
||||
throw e2;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeQuietly(ServerSocket serverSocket) {
|
||||
if (serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
sources/okhttp3/internal/Version.java
Normal file
11
sources/okhttp3/internal/Version.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package okhttp3.internal;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Version {
|
||||
private Version() {
|
||||
}
|
||||
|
||||
public static String userAgent() {
|
||||
return "okhttp/3.11.0";
|
||||
}
|
||||
}
|
||||
166
sources/okhttp3/internal/cache/CacheInterceptor.java
vendored
Normal file
166
sources/okhttp3/internal/cache/CacheInterceptor.java
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.cache.CacheStrategy;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.http.HttpMethod;
|
||||
import okhttp3.internal.http.RealResponseBody;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class CacheInterceptor implements Interceptor {
|
||||
final InternalCache cache;
|
||||
|
||||
public CacheInterceptor(InternalCache internalCache) {
|
||||
this.cache = internalCache;
|
||||
}
|
||||
|
||||
private Response cacheWritingResponse(final CacheRequest cacheRequest, Response response) throws IOException {
|
||||
Sink body;
|
||||
if (cacheRequest == null || (body = cacheRequest.body()) == null) {
|
||||
return response;
|
||||
}
|
||||
final BufferedSource source = response.body().source();
|
||||
final BufferedSink buffer = Okio.buffer(body);
|
||||
return response.newBuilder().body(new RealResponseBody(response.header("Content-Type"), response.body().contentLength(), Okio.buffer(new Source() { // from class: okhttp3.internal.cache.CacheInterceptor.1
|
||||
boolean cacheRequestClosed;
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (!this.cacheRequestClosed && !Util.discard(this, 100, TimeUnit.MILLISECONDS)) {
|
||||
this.cacheRequestClosed = true;
|
||||
cacheRequest.abort();
|
||||
}
|
||||
source.close();
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public long read(Buffer buffer2, long j) throws IOException {
|
||||
try {
|
||||
long read = source.read(buffer2, j);
|
||||
if (read != -1) {
|
||||
buffer2.copyTo(buffer.buffer(), buffer2.size() - read, read);
|
||||
buffer.emitCompleteSegments();
|
||||
return read;
|
||||
}
|
||||
if (!this.cacheRequestClosed) {
|
||||
this.cacheRequestClosed = true;
|
||||
buffer.close();
|
||||
}
|
||||
return -1L;
|
||||
} catch (IOException e) {
|
||||
if (!this.cacheRequestClosed) {
|
||||
this.cacheRequestClosed = true;
|
||||
cacheRequest.abort();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return source.timeout();
|
||||
}
|
||||
}))).build();
|
||||
}
|
||||
|
||||
private static Headers combine(Headers headers, Headers headers2) {
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String name = headers.name(i);
|
||||
String value = headers.value(i);
|
||||
if ((!"Warning".equalsIgnoreCase(name) || !value.startsWith("1")) && (isContentSpecificHeader(name) || !isEndToEnd(name) || headers2.get(name) == null)) {
|
||||
Internal.instance.addLenient(builder, name, value);
|
||||
}
|
||||
}
|
||||
int size2 = headers2.size();
|
||||
for (int i2 = 0; i2 < size2; i2++) {
|
||||
String name2 = headers2.name(i2);
|
||||
if (!isContentSpecificHeader(name2) && isEndToEnd(name2)) {
|
||||
Internal.instance.addLenient(builder, name2, headers2.value(i2));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static boolean isContentSpecificHeader(String str) {
|
||||
return "Content-Length".equalsIgnoreCase(str) || "Content-Encoding".equalsIgnoreCase(str) || "Content-Type".equalsIgnoreCase(str);
|
||||
}
|
||||
|
||||
static boolean isEndToEnd(String str) {
|
||||
return ("Connection".equalsIgnoreCase(str) || "Keep-Alive".equalsIgnoreCase(str) || "Proxy-Authenticate".equalsIgnoreCase(str) || "Proxy-Authorization".equalsIgnoreCase(str) || "TE".equalsIgnoreCase(str) || "Trailers".equalsIgnoreCase(str) || "Transfer-Encoding".equalsIgnoreCase(str) || "Upgrade".equalsIgnoreCase(str)) ? false : true;
|
||||
}
|
||||
|
||||
private static Response stripBody(Response response) {
|
||||
return (response == null || response.body() == null) ? response : response.newBuilder().body(null).build();
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
InternalCache internalCache = this.cache;
|
||||
Response response = internalCache != null ? internalCache.get(chain.request()) : null;
|
||||
CacheStrategy cacheStrategy = new CacheStrategy.Factory(System.currentTimeMillis(), chain.request(), response).get();
|
||||
Request request = cacheStrategy.networkRequest;
|
||||
Response response2 = cacheStrategy.cacheResponse;
|
||||
InternalCache internalCache2 = this.cache;
|
||||
if (internalCache2 != null) {
|
||||
internalCache2.trackResponse(cacheStrategy);
|
||||
}
|
||||
if (response != null && response2 == null) {
|
||||
Util.closeQuietly(response.body());
|
||||
}
|
||||
if (request == null && response2 == null) {
|
||||
return new Response.Builder().request(chain.request()).protocol(Protocol.HTTP_1_1).code(504).message("Unsatisfiable Request (only-if-cached)").body(Util.EMPTY_RESPONSE).sentRequestAtMillis(-1L).receivedResponseAtMillis(System.currentTimeMillis()).build();
|
||||
}
|
||||
if (request == null) {
|
||||
return response2.newBuilder().cacheResponse(stripBody(response2)).build();
|
||||
}
|
||||
try {
|
||||
Response proceed = chain.proceed(request);
|
||||
if (proceed == null && response != null) {
|
||||
}
|
||||
if (response2 != null) {
|
||||
if (proceed.code() == 304) {
|
||||
Response build = response2.newBuilder().headers(combine(response2.headers(), proceed.headers())).sentRequestAtMillis(proceed.sentRequestAtMillis()).receivedResponseAtMillis(proceed.receivedResponseAtMillis()).cacheResponse(stripBody(response2)).networkResponse(stripBody(proceed)).build();
|
||||
proceed.body().close();
|
||||
this.cache.trackConditionalCacheHit();
|
||||
this.cache.update(response2, build);
|
||||
return build;
|
||||
}
|
||||
Util.closeQuietly(response2.body());
|
||||
}
|
||||
Response build2 = proceed.newBuilder().cacheResponse(stripBody(response2)).networkResponse(stripBody(proceed)).build();
|
||||
if (this.cache != null) {
|
||||
if (HttpHeaders.hasBody(build2) && CacheStrategy.isCacheable(build2, request)) {
|
||||
return cacheWritingResponse(this.cache.put(build2), build2);
|
||||
}
|
||||
if (HttpMethod.invalidatesCache(request.method())) {
|
||||
try {
|
||||
this.cache.remove(request);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return build2;
|
||||
} finally {
|
||||
if (response != null) {
|
||||
Util.closeQuietly(response.body());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
sources/okhttp3/internal/cache/CacheRequest.java
vendored
Normal file
11
sources/okhttp3/internal/cache/CacheRequest.java
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface CacheRequest {
|
||||
void abort();
|
||||
|
||||
Sink body() throws IOException;
|
||||
}
|
||||
243
sources/okhttp3/internal/cache/CacheStrategy.java
vendored
Normal file
243
sources/okhttp3/internal/cache/CacheStrategy.java
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.CacheControl;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.http.HttpDate;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class CacheStrategy {
|
||||
public final Response cacheResponse;
|
||||
public final Request networkRequest;
|
||||
|
||||
public static class Factory {
|
||||
private int ageSeconds;
|
||||
final Response cacheResponse;
|
||||
private String etag;
|
||||
private Date expires;
|
||||
private Date lastModified;
|
||||
private String lastModifiedString;
|
||||
final long nowMillis;
|
||||
private long receivedResponseMillis;
|
||||
final Request request;
|
||||
private long sentRequestMillis;
|
||||
private Date servedDate;
|
||||
private String servedDateString;
|
||||
|
||||
public Factory(long j, Request request, Response response) {
|
||||
this.ageSeconds = -1;
|
||||
this.nowMillis = j;
|
||||
this.request = request;
|
||||
this.cacheResponse = response;
|
||||
if (response != null) {
|
||||
this.sentRequestMillis = response.sentRequestAtMillis();
|
||||
this.receivedResponseMillis = response.receivedResponseAtMillis();
|
||||
Headers headers = response.headers();
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String name = headers.name(i);
|
||||
String value = headers.value(i);
|
||||
if ("Date".equalsIgnoreCase(name)) {
|
||||
this.servedDate = HttpDate.parse(value);
|
||||
this.servedDateString = value;
|
||||
} else if ("Expires".equalsIgnoreCase(name)) {
|
||||
this.expires = HttpDate.parse(value);
|
||||
} else if ("Last-Modified".equalsIgnoreCase(name)) {
|
||||
this.lastModified = HttpDate.parse(value);
|
||||
this.lastModifiedString = value;
|
||||
} else if ("ETag".equalsIgnoreCase(name)) {
|
||||
this.etag = value;
|
||||
} else if ("Age".equalsIgnoreCase(name)) {
|
||||
this.ageSeconds = HttpHeaders.parseSeconds(value, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long cacheResponseAge() {
|
||||
Date date = this.servedDate;
|
||||
long max = date != null ? Math.max(0L, this.receivedResponseMillis - date.getTime()) : 0L;
|
||||
int i = this.ageSeconds;
|
||||
if (i != -1) {
|
||||
max = Math.max(max, TimeUnit.SECONDS.toMillis(i));
|
||||
}
|
||||
long j = this.receivedResponseMillis;
|
||||
return max + (j - this.sentRequestMillis) + (this.nowMillis - j);
|
||||
}
|
||||
|
||||
private long computeFreshnessLifetime() {
|
||||
if (this.cacheResponse.cacheControl().maxAgeSeconds() != -1) {
|
||||
return TimeUnit.SECONDS.toMillis(r0.maxAgeSeconds());
|
||||
}
|
||||
if (this.expires != null) {
|
||||
Date date = this.servedDate;
|
||||
long time = this.expires.getTime() - (date != null ? date.getTime() : this.receivedResponseMillis);
|
||||
if (time > 0) {
|
||||
return time;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
if (this.lastModified == null || this.cacheResponse.request().url().query() != null) {
|
||||
return 0L;
|
||||
}
|
||||
Date date2 = this.servedDate;
|
||||
long time2 = (date2 != null ? date2.getTime() : this.sentRequestMillis) - this.lastModified.getTime();
|
||||
if (time2 > 0) {
|
||||
return time2 / 10;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private CacheStrategy getCandidate() {
|
||||
if (this.cacheResponse == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
if (this.request.isHttps() && this.cacheResponse.handshake() == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
if (!CacheStrategy.isCacheable(this.cacheResponse, this.request)) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
CacheControl cacheControl = this.request.cacheControl();
|
||||
if (cacheControl.noCache() || hasConditions(this.request)) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
CacheControl cacheControl2 = this.cacheResponse.cacheControl();
|
||||
if (cacheControl2.immutable()) {
|
||||
return new CacheStrategy(null, this.cacheResponse);
|
||||
}
|
||||
long cacheResponseAge = cacheResponseAge();
|
||||
long computeFreshnessLifetime = computeFreshnessLifetime();
|
||||
if (cacheControl.maxAgeSeconds() != -1) {
|
||||
computeFreshnessLifetime = Math.min(computeFreshnessLifetime, TimeUnit.SECONDS.toMillis(cacheControl.maxAgeSeconds()));
|
||||
}
|
||||
long j = 0;
|
||||
long millis = cacheControl.minFreshSeconds() != -1 ? TimeUnit.SECONDS.toMillis(cacheControl.minFreshSeconds()) : 0L;
|
||||
if (!cacheControl2.mustRevalidate() && cacheControl.maxStaleSeconds() != -1) {
|
||||
j = TimeUnit.SECONDS.toMillis(cacheControl.maxStaleSeconds());
|
||||
}
|
||||
if (!cacheControl2.noCache()) {
|
||||
long j2 = millis + cacheResponseAge;
|
||||
if (j2 < j + computeFreshnessLifetime) {
|
||||
Response.Builder newBuilder = this.cacheResponse.newBuilder();
|
||||
if (j2 >= computeFreshnessLifetime) {
|
||||
newBuilder.addHeader("Warning", "110 HttpURLConnection \"Response is stale\"");
|
||||
}
|
||||
if (cacheResponseAge > 86400000 && isFreshnessLifetimeHeuristic()) {
|
||||
newBuilder.addHeader("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
|
||||
}
|
||||
return new CacheStrategy(null, newBuilder.build());
|
||||
}
|
||||
}
|
||||
String str = this.etag;
|
||||
String str2 = "If-Modified-Since";
|
||||
if (str != null) {
|
||||
str2 = "If-None-Match";
|
||||
} else if (this.lastModified != null) {
|
||||
str = this.lastModifiedString;
|
||||
} else {
|
||||
if (this.servedDate == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
str = this.servedDateString;
|
||||
}
|
||||
Headers.Builder newBuilder2 = this.request.headers().newBuilder();
|
||||
Internal.instance.addLenient(newBuilder2, str2, str);
|
||||
return new CacheStrategy(this.request.newBuilder().headers(newBuilder2.build()).build(), this.cacheResponse);
|
||||
}
|
||||
|
||||
private static boolean hasConditions(Request request) {
|
||||
return (request.header("If-Modified-Since") == null && request.header("If-None-Match") == null) ? false : true;
|
||||
}
|
||||
|
||||
private boolean isFreshnessLifetimeHeuristic() {
|
||||
return this.cacheResponse.cacheControl().maxAgeSeconds() == -1 && this.expires == null;
|
||||
}
|
||||
|
||||
public CacheStrategy get() {
|
||||
CacheStrategy candidate = getCandidate();
|
||||
return (candidate.networkRequest == null || !this.request.cacheControl().onlyIfCached()) ? candidate : new CacheStrategy(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
CacheStrategy(Request request, Response response) {
|
||||
this.networkRequest = request;
|
||||
this.cacheResponse = response;
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:31:0x0056, code lost:
|
||||
|
||||
if (r3.cacheControl().isPrivate() == false) goto L33;
|
||||
*/
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public static boolean isCacheable(okhttp3.Response r3, okhttp3.Request r4) {
|
||||
/*
|
||||
int r0 = r3.code()
|
||||
r1 = 200(0xc8, float:2.8E-43)
|
||||
r2 = 0
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 410(0x19a, float:5.75E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 414(0x19e, float:5.8E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 501(0x1f5, float:7.02E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 203(0xcb, float:2.84E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 204(0xcc, float:2.86E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 307(0x133, float:4.3E-43)
|
||||
if (r0 == r1) goto L31
|
||||
r1 = 308(0x134, float:4.32E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 404(0x194, float:5.66E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 405(0x195, float:5.68E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
switch(r0) {
|
||||
case 300: goto L5a;
|
||||
case 301: goto L5a;
|
||||
case 302: goto L31;
|
||||
default: goto L30;
|
||||
}
|
||||
L30:
|
||||
goto L59
|
||||
L31:
|
||||
java.lang.String r0 = "Expires"
|
||||
java.lang.String r0 = r3.header(r0)
|
||||
if (r0 != 0) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
int r0 = r0.maxAgeSeconds()
|
||||
r1 = -1
|
||||
if (r0 != r1) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
boolean r0 = r0.isPublic()
|
||||
if (r0 != 0) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
boolean r0 = r0.isPrivate()
|
||||
if (r0 == 0) goto L59
|
||||
goto L5a
|
||||
L59:
|
||||
return r2
|
||||
L5a:
|
||||
okhttp3.CacheControl r3 = r3.cacheControl()
|
||||
boolean r3 = r3.noStore()
|
||||
if (r3 != 0) goto L6f
|
||||
okhttp3.CacheControl r3 = r4.cacheControl()
|
||||
boolean r3 = r3.noStore()
|
||||
if (r3 != 0) goto L6f
|
||||
r2 = 1
|
||||
L6f:
|
||||
return r2
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.cache.CacheStrategy.isCacheable(okhttp3.Response, okhttp3.Request):boolean");
|
||||
}
|
||||
}
|
||||
794
sources/okhttp3/internal/cache/DiskLruCache.java
vendored
Normal file
794
sources/okhttp3/internal/cache/DiskLruCache.java
vendored
Normal file
@@ -0,0 +1,794 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.io.FileSystem;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class DiskLruCache implements Closeable, Flushable {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
static final long ANY_SEQUENCE_NUMBER = -1;
|
||||
private static final String CLEAN = "CLEAN";
|
||||
private static final String DIRTY = "DIRTY";
|
||||
static final String JOURNAL_FILE = "journal";
|
||||
static final String JOURNAL_FILE_BACKUP = "journal.bkp";
|
||||
static final String JOURNAL_FILE_TEMP = "journal.tmp";
|
||||
static final Pattern LEGAL_KEY_PATTERN = Pattern.compile("[a-z0-9_-]{1,120}");
|
||||
static final String MAGIC = "libcore.io.DiskLruCache";
|
||||
private static final String READ = "READ";
|
||||
private static final String REMOVE = "REMOVE";
|
||||
static final String VERSION_1 = "1";
|
||||
private final int appVersion;
|
||||
boolean closed;
|
||||
final File directory;
|
||||
private final Executor executor;
|
||||
final FileSystem fileSystem;
|
||||
boolean hasJournalErrors;
|
||||
boolean initialized;
|
||||
private final File journalFile;
|
||||
private final File journalFileBackup;
|
||||
private final File journalFileTmp;
|
||||
BufferedSink journalWriter;
|
||||
private long maxSize;
|
||||
boolean mostRecentRebuildFailed;
|
||||
boolean mostRecentTrimFailed;
|
||||
int redundantOpCount;
|
||||
final int valueCount;
|
||||
private long size = 0;
|
||||
final LinkedHashMap<String, Entry> lruEntries = new LinkedHashMap<>(0, 0.75f, true);
|
||||
private long nextSequenceNumber = 0;
|
||||
private final Runnable cleanupRunnable = new Runnable() { // from class: okhttp3.internal.cache.DiskLruCache.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if ((!DiskLruCache.this.initialized) || DiskLruCache.this.closed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.trimToSize();
|
||||
} catch (IOException unused) {
|
||||
DiskLruCache.this.mostRecentTrimFailed = true;
|
||||
}
|
||||
try {
|
||||
if (DiskLruCache.this.journalRebuildRequired()) {
|
||||
DiskLruCache.this.rebuildJournal();
|
||||
DiskLruCache.this.redundantOpCount = 0;
|
||||
}
|
||||
} catch (IOException unused2) {
|
||||
DiskLruCache.this.mostRecentRebuildFailed = true;
|
||||
DiskLruCache.this.journalWriter = Okio.buffer(Okio.blackhole());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public final class Editor {
|
||||
private boolean done;
|
||||
final Entry entry;
|
||||
final boolean[] written;
|
||||
|
||||
Editor(Entry entry) {
|
||||
this.entry = entry;
|
||||
this.written = entry.readable ? null : new boolean[DiskLruCache.this.valueCount];
|
||||
}
|
||||
|
||||
public void abort() throws IOException {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor == this) {
|
||||
DiskLruCache.this.completeEdit(this, false);
|
||||
}
|
||||
this.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void abortUnlessCommitted() {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (!this.done && this.entry.currentEditor == this) {
|
||||
try {
|
||||
DiskLruCache.this.completeEdit(this, false);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void commit() throws IOException {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor == this) {
|
||||
DiskLruCache.this.completeEdit(this, true);
|
||||
}
|
||||
this.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void detach() {
|
||||
if (this.entry.currentEditor != this) {
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while (true) {
|
||||
DiskLruCache diskLruCache = DiskLruCache.this;
|
||||
if (i >= diskLruCache.valueCount) {
|
||||
this.entry.currentEditor = null;
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
diskLruCache.fileSystem.delete(this.entry.dirtyFiles[i]);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Sink newSink(int i) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor != this) {
|
||||
return Okio.blackhole();
|
||||
}
|
||||
if (!this.entry.readable) {
|
||||
this.written[i] = true;
|
||||
}
|
||||
try {
|
||||
return new FaultHidingSink(DiskLruCache.this.fileSystem.sink(this.entry.dirtyFiles[i])) { // from class: okhttp3.internal.cache.DiskLruCache.Editor.1
|
||||
@Override // okhttp3.internal.cache.FaultHidingSink
|
||||
protected void onException(IOException iOException) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
Editor.this.detach();
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (FileNotFoundException unused) {
|
||||
return Okio.blackhole();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Source newSource(int i) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (!this.entry.readable || this.entry.currentEditor != this) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return DiskLruCache.this.fileSystem.source(this.entry.cleanFiles[i]);
|
||||
} catch (FileNotFoundException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class Entry {
|
||||
final File[] cleanFiles;
|
||||
Editor currentEditor;
|
||||
final File[] dirtyFiles;
|
||||
final String key;
|
||||
final long[] lengths;
|
||||
boolean readable;
|
||||
long sequenceNumber;
|
||||
|
||||
Entry(String str) {
|
||||
this.key = str;
|
||||
int i = DiskLruCache.this.valueCount;
|
||||
this.lengths = new long[i];
|
||||
this.cleanFiles = new File[i];
|
||||
this.dirtyFiles = new File[i];
|
||||
StringBuilder sb = new StringBuilder(str);
|
||||
sb.append('.');
|
||||
int length = sb.length();
|
||||
for (int i2 = 0; i2 < DiskLruCache.this.valueCount; i2++) {
|
||||
sb.append(i2);
|
||||
this.cleanFiles[i2] = new File(DiskLruCache.this.directory, sb.toString());
|
||||
sb.append(".tmp");
|
||||
this.dirtyFiles[i2] = new File(DiskLruCache.this.directory, sb.toString());
|
||||
sb.setLength(length);
|
||||
}
|
||||
}
|
||||
|
||||
private IOException invalidLengths(String[] strArr) throws IOException {
|
||||
throw new IOException("unexpected journal line: " + Arrays.toString(strArr));
|
||||
}
|
||||
|
||||
void setLengths(String[] strArr) throws IOException {
|
||||
if (strArr.length != DiskLruCache.this.valueCount) {
|
||||
throw invalidLengths(strArr);
|
||||
}
|
||||
for (int i = 0; i < strArr.length; i++) {
|
||||
try {
|
||||
this.lengths[i] = Long.parseLong(strArr[i]);
|
||||
} catch (NumberFormatException unused) {
|
||||
throw invalidLengths(strArr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Snapshot snapshot() {
|
||||
if (!Thread.holdsLock(DiskLruCache.this)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
Source[] sourceArr = new Source[DiskLruCache.this.valueCount];
|
||||
long[] jArr = (long[]) this.lengths.clone();
|
||||
for (int i = 0; i < DiskLruCache.this.valueCount; i++) {
|
||||
try {
|
||||
sourceArr[i] = DiskLruCache.this.fileSystem.source(this.cleanFiles[i]);
|
||||
} catch (FileNotFoundException unused) {
|
||||
for (int i2 = 0; i2 < DiskLruCache.this.valueCount && sourceArr[i2] != null; i2++) {
|
||||
Util.closeQuietly(sourceArr[i2]);
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.removeEntry(this);
|
||||
return null;
|
||||
} catch (IOException unused2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DiskLruCache.this.new Snapshot(this.key, this.sequenceNumber, sourceArr, jArr);
|
||||
}
|
||||
|
||||
void writeLengths(BufferedSink bufferedSink) throws IOException {
|
||||
for (long j : this.lengths) {
|
||||
bufferedSink.writeByte(32).writeDecimalLong(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class Snapshot implements Closeable {
|
||||
private final String key;
|
||||
private final long[] lengths;
|
||||
private final long sequenceNumber;
|
||||
private final Source[] sources;
|
||||
|
||||
Snapshot(String str, long j, Source[] sourceArr, long[] jArr) {
|
||||
this.key = str;
|
||||
this.sequenceNumber = j;
|
||||
this.sources = sourceArr;
|
||||
this.lengths = jArr;
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() {
|
||||
for (Source source : this.sources) {
|
||||
Util.closeQuietly(source);
|
||||
}
|
||||
}
|
||||
|
||||
public Editor edit() throws IOException {
|
||||
return DiskLruCache.this.edit(this.key, this.sequenceNumber);
|
||||
}
|
||||
|
||||
public long getLength(int i) {
|
||||
return this.lengths[i];
|
||||
}
|
||||
|
||||
public Source getSource(int i) {
|
||||
return this.sources[i];
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
||||
DiskLruCache(FileSystem fileSystem, File file, int i, int i2, long j, Executor executor) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.directory = file;
|
||||
this.appVersion = i;
|
||||
this.journalFile = new File(file, JOURNAL_FILE);
|
||||
this.journalFileTmp = new File(file, JOURNAL_FILE_TEMP);
|
||||
this.journalFileBackup = new File(file, JOURNAL_FILE_BACKUP);
|
||||
this.valueCount = i2;
|
||||
this.maxSize = j;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
private synchronized void checkNotClosed() {
|
||||
if (isClosed()) {
|
||||
throw new IllegalStateException("cache is closed");
|
||||
}
|
||||
}
|
||||
|
||||
public static DiskLruCache create(FileSystem fileSystem, File file, int i, int i2, long j) {
|
||||
if (j <= 0) {
|
||||
throw new IllegalArgumentException("maxSize <= 0");
|
||||
}
|
||||
if (i2 > 0) {
|
||||
return new DiskLruCache(fileSystem, file, i, i2, j, new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(), Util.threadFactory("OkHttp DiskLruCache", true)));
|
||||
}
|
||||
throw new IllegalArgumentException("valueCount <= 0");
|
||||
}
|
||||
|
||||
private BufferedSink newJournalWriter() throws FileNotFoundException {
|
||||
return Okio.buffer(new FaultHidingSink(this.fileSystem.appendingSink(this.journalFile)) { // from class: okhttp3.internal.cache.DiskLruCache.2
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
|
||||
@Override // okhttp3.internal.cache.FaultHidingSink
|
||||
protected void onException(IOException iOException) {
|
||||
DiskLruCache.this.hasJournalErrors = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processJournal() throws IOException {
|
||||
this.fileSystem.delete(this.journalFileTmp);
|
||||
Iterator<Entry> it = this.lruEntries.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry next = it.next();
|
||||
int i = 0;
|
||||
if (next.currentEditor == null) {
|
||||
while (i < this.valueCount) {
|
||||
this.size += next.lengths[i];
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
next.currentEditor = null;
|
||||
while (i < this.valueCount) {
|
||||
this.fileSystem.delete(next.cleanFiles[i]);
|
||||
this.fileSystem.delete(next.dirtyFiles[i]);
|
||||
i++;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readJournal() throws IOException {
|
||||
BufferedSource buffer = Okio.buffer(this.fileSystem.source(this.journalFile));
|
||||
try {
|
||||
String readUtf8LineStrict = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict2 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict3 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict4 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict5 = buffer.readUtf8LineStrict();
|
||||
if (!MAGIC.equals(readUtf8LineStrict) || !"1".equals(readUtf8LineStrict2) || !Integer.toString(this.appVersion).equals(readUtf8LineStrict3) || !Integer.toString(this.valueCount).equals(readUtf8LineStrict4) || !"".equals(readUtf8LineStrict5)) {
|
||||
throw new IOException("unexpected journal header: [" + readUtf8LineStrict + ", " + readUtf8LineStrict2 + ", " + readUtf8LineStrict4 + ", " + readUtf8LineStrict5 + "]");
|
||||
}
|
||||
int i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
readJournalLine(buffer.readUtf8LineStrict());
|
||||
i++;
|
||||
} catch (EOFException unused) {
|
||||
this.redundantOpCount = i - this.lruEntries.size();
|
||||
if (buffer.exhausted()) {
|
||||
this.journalWriter = newJournalWriter();
|
||||
} else {
|
||||
rebuildJournal();
|
||||
}
|
||||
Util.closeQuietly(buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
Util.closeQuietly(buffer);
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
private void readJournalLine(String str) throws IOException {
|
||||
String substring;
|
||||
int indexOf = str.indexOf(32);
|
||||
if (indexOf == -1) {
|
||||
throw new IOException("unexpected journal line: " + str);
|
||||
}
|
||||
int i = indexOf + 1;
|
||||
int indexOf2 = str.indexOf(32, i);
|
||||
if (indexOf2 == -1) {
|
||||
substring = str.substring(i);
|
||||
if (indexOf == 6 && str.startsWith(REMOVE)) {
|
||||
this.lruEntries.remove(substring);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
substring = str.substring(i, indexOf2);
|
||||
}
|
||||
Entry entry = this.lruEntries.get(substring);
|
||||
if (entry == null) {
|
||||
entry = new Entry(substring);
|
||||
this.lruEntries.put(substring, entry);
|
||||
}
|
||||
if (indexOf2 != -1 && indexOf == 5 && str.startsWith(CLEAN)) {
|
||||
String[] split = str.substring(indexOf2 + 1).split(" ");
|
||||
entry.readable = true;
|
||||
entry.currentEditor = null;
|
||||
entry.setLengths(split);
|
||||
return;
|
||||
}
|
||||
if (indexOf2 == -1 && indexOf == 5 && str.startsWith(DIRTY)) {
|
||||
entry.currentEditor = new Editor(entry);
|
||||
return;
|
||||
}
|
||||
if (indexOf2 == -1 && indexOf == 4 && str.startsWith(READ)) {
|
||||
return;
|
||||
}
|
||||
throw new IOException("unexpected journal line: " + str);
|
||||
}
|
||||
|
||||
private void validateKey(String str) {
|
||||
if (LEGAL_KEY_PATTERN.matcher(str).matches()) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("keys must match regex [a-z0-9_-]{1,120}: \"" + str + "\"");
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public synchronized void close() throws IOException {
|
||||
if (this.initialized && !this.closed) {
|
||||
for (Entry entry : (Entry[]) this.lruEntries.values().toArray(new Entry[this.lruEntries.size()])) {
|
||||
if (entry.currentEditor != null) {
|
||||
entry.currentEditor.abort();
|
||||
}
|
||||
}
|
||||
trimToSize();
|
||||
this.journalWriter.close();
|
||||
this.journalWriter = null;
|
||||
this.closed = true;
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
synchronized void completeEdit(Editor editor, boolean z) throws IOException {
|
||||
Entry entry = editor.entry;
|
||||
if (entry.currentEditor != editor) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (z && !entry.readable) {
|
||||
for (int i = 0; i < this.valueCount; i++) {
|
||||
if (!editor.written[i]) {
|
||||
editor.abort();
|
||||
throw new IllegalStateException("Newly created entry didn't create value for index " + i);
|
||||
}
|
||||
if (!this.fileSystem.exists(entry.dirtyFiles[i])) {
|
||||
editor.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i2 = 0; i2 < this.valueCount; i2++) {
|
||||
File file = entry.dirtyFiles[i2];
|
||||
if (!z) {
|
||||
this.fileSystem.delete(file);
|
||||
} else if (this.fileSystem.exists(file)) {
|
||||
File file2 = entry.cleanFiles[i2];
|
||||
this.fileSystem.rename(file, file2);
|
||||
long j = entry.lengths[i2];
|
||||
long size = this.fileSystem.size(file2);
|
||||
entry.lengths[i2] = size;
|
||||
this.size = (this.size - j) + size;
|
||||
}
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
entry.currentEditor = null;
|
||||
if (entry.readable || z) {
|
||||
entry.readable = true;
|
||||
this.journalWriter.writeUtf8(CLEAN).writeByte(32);
|
||||
this.journalWriter.writeUtf8(entry.key);
|
||||
entry.writeLengths(this.journalWriter);
|
||||
this.journalWriter.writeByte(10);
|
||||
if (z) {
|
||||
long j2 = this.nextSequenceNumber;
|
||||
this.nextSequenceNumber = 1 + j2;
|
||||
entry.sequenceNumber = j2;
|
||||
}
|
||||
} else {
|
||||
this.lruEntries.remove(entry.key);
|
||||
this.journalWriter.writeUtf8(REMOVE).writeByte(32);
|
||||
this.journalWriter.writeUtf8(entry.key);
|
||||
this.journalWriter.writeByte(10);
|
||||
}
|
||||
this.journalWriter.flush();
|
||||
if (this.size > this.maxSize || journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() throws IOException {
|
||||
close();
|
||||
this.fileSystem.deleteContents(this.directory);
|
||||
}
|
||||
|
||||
public Editor edit(String str) throws IOException {
|
||||
return edit(str, -1L);
|
||||
}
|
||||
|
||||
public synchronized void evictAll() throws IOException {
|
||||
initialize();
|
||||
for (Entry entry : (Entry[]) this.lruEntries.values().toArray(new Entry[this.lruEntries.size()])) {
|
||||
removeEntry(entry);
|
||||
}
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
|
||||
@Override // java.io.Flushable
|
||||
public synchronized void flush() throws IOException {
|
||||
if (this.initialized) {
|
||||
checkNotClosed();
|
||||
trimToSize();
|
||||
this.journalWriter.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Snapshot get(String str) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (entry != null && entry.readable) {
|
||||
Snapshot snapshot = entry.snapshot();
|
||||
if (snapshot == null) {
|
||||
return null;
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
this.journalWriter.writeUtf8(READ).writeByte(32).writeUtf8(str).writeByte(10);
|
||||
if (journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getDirectory() {
|
||||
return this.directory;
|
||||
}
|
||||
|
||||
public synchronized long getMaxSize() {
|
||||
return this.maxSize;
|
||||
}
|
||||
|
||||
public synchronized void initialize() throws IOException {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
if (this.fileSystem.exists(this.journalFileBackup)) {
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
this.fileSystem.delete(this.journalFileBackup);
|
||||
} else {
|
||||
this.fileSystem.rename(this.journalFileBackup, this.journalFile);
|
||||
}
|
||||
}
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
try {
|
||||
readJournal();
|
||||
processJournal();
|
||||
this.initialized = true;
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Platform.get().log(5, "DiskLruCache " + this.directory + " is corrupt: " + e.getMessage() + ", removing", e);
|
||||
try {
|
||||
delete();
|
||||
this.closed = false;
|
||||
} catch (Throwable th) {
|
||||
this.closed = false;
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
}
|
||||
rebuildJournal();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public synchronized boolean isClosed() {
|
||||
return this.closed;
|
||||
}
|
||||
|
||||
boolean journalRebuildRequired() {
|
||||
int i = this.redundantOpCount;
|
||||
return i >= 2000 && i >= this.lruEntries.size();
|
||||
}
|
||||
|
||||
synchronized void rebuildJournal() throws IOException {
|
||||
if (this.journalWriter != null) {
|
||||
this.journalWriter.close();
|
||||
}
|
||||
BufferedSink buffer = Okio.buffer(this.fileSystem.sink(this.journalFileTmp));
|
||||
try {
|
||||
buffer.writeUtf8(MAGIC).writeByte(10);
|
||||
buffer.writeUtf8("1").writeByte(10);
|
||||
buffer.writeDecimalLong(this.appVersion).writeByte(10);
|
||||
buffer.writeDecimalLong(this.valueCount).writeByte(10);
|
||||
buffer.writeByte(10);
|
||||
for (Entry entry : this.lruEntries.values()) {
|
||||
if (entry.currentEditor != null) {
|
||||
buffer.writeUtf8(DIRTY).writeByte(32);
|
||||
buffer.writeUtf8(entry.key);
|
||||
buffer.writeByte(10);
|
||||
} else {
|
||||
buffer.writeUtf8(CLEAN).writeByte(32);
|
||||
buffer.writeUtf8(entry.key);
|
||||
entry.writeLengths(buffer);
|
||||
buffer.writeByte(10);
|
||||
}
|
||||
}
|
||||
buffer.close();
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
this.fileSystem.rename(this.journalFile, this.journalFileBackup);
|
||||
}
|
||||
this.fileSystem.rename(this.journalFileTmp, this.journalFile);
|
||||
this.fileSystem.delete(this.journalFileBackup);
|
||||
this.journalWriter = newJournalWriter();
|
||||
this.hasJournalErrors = false;
|
||||
this.mostRecentRebuildFailed = false;
|
||||
} catch (Throwable th) {
|
||||
buffer.close();
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean remove(String str) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
boolean removeEntry = removeEntry(entry);
|
||||
if (removeEntry && this.size <= this.maxSize) {
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
return removeEntry;
|
||||
}
|
||||
|
||||
boolean removeEntry(Entry entry) throws IOException {
|
||||
Editor editor = entry.currentEditor;
|
||||
if (editor != null) {
|
||||
editor.detach();
|
||||
}
|
||||
for (int i = 0; i < this.valueCount; i++) {
|
||||
this.fileSystem.delete(entry.cleanFiles[i]);
|
||||
long j = this.size;
|
||||
long[] jArr = entry.lengths;
|
||||
this.size = j - jArr[i];
|
||||
jArr[i] = 0;
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
this.journalWriter.writeUtf8(REMOVE).writeByte(32).writeUtf8(entry.key).writeByte(10);
|
||||
this.lruEntries.remove(entry.key);
|
||||
if (journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void setMaxSize(long j) {
|
||||
this.maxSize = j;
|
||||
if (this.initialized) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long size() throws IOException {
|
||||
initialize();
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public synchronized Iterator<Snapshot> snapshots() throws IOException {
|
||||
initialize();
|
||||
return new Iterator<Snapshot>() { // from class: okhttp3.internal.cache.DiskLruCache.3
|
||||
final Iterator<Entry> delegate;
|
||||
Snapshot nextSnapshot;
|
||||
Snapshot removeSnapshot;
|
||||
|
||||
{
|
||||
this.delegate = new ArrayList(DiskLruCache.this.lruEntries.values()).iterator();
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public boolean hasNext() {
|
||||
if (this.nextSnapshot != null) {
|
||||
return true;
|
||||
}
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (DiskLruCache.this.closed) {
|
||||
return false;
|
||||
}
|
||||
while (this.delegate.hasNext()) {
|
||||
Snapshot snapshot = this.delegate.next().snapshot();
|
||||
if (snapshot != null) {
|
||||
this.nextSnapshot = snapshot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public void remove() {
|
||||
Snapshot snapshot = this.removeSnapshot;
|
||||
if (snapshot == null) {
|
||||
throw new IllegalStateException("remove() before next()");
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.remove(snapshot.key);
|
||||
} catch (IOException unused) {
|
||||
} catch (Throwable th) {
|
||||
this.removeSnapshot = null;
|
||||
throw th;
|
||||
}
|
||||
this.removeSnapshot = null;
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public Snapshot next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
this.removeSnapshot = this.nextSnapshot;
|
||||
this.nextSnapshot = null;
|
||||
return this.removeSnapshot;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void trimToSize() throws IOException {
|
||||
while (this.size > this.maxSize) {
|
||||
removeEntry(this.lruEntries.values().iterator().next());
|
||||
}
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
|
||||
synchronized Editor edit(String str, long j) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (j != -1 && (entry == null || entry.sequenceNumber != j)) {
|
||||
return null;
|
||||
}
|
||||
if (entry != null && entry.currentEditor != null) {
|
||||
return null;
|
||||
}
|
||||
if (!this.mostRecentTrimFailed && !this.mostRecentRebuildFailed) {
|
||||
this.journalWriter.writeUtf8(DIRTY).writeByte(32).writeUtf8(str).writeByte(10);
|
||||
this.journalWriter.flush();
|
||||
if (this.hasJournalErrors) {
|
||||
return null;
|
||||
}
|
||||
if (entry == null) {
|
||||
entry = new Entry(str);
|
||||
this.lruEntries.put(str, entry);
|
||||
}
|
||||
Editor editor = new Editor(entry);
|
||||
entry.currentEditor = editor;
|
||||
return editor;
|
||||
}
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
58
sources/okhttp3/internal/cache/FaultHidingSink.java
vendored
Normal file
58
sources/okhttp3/internal/cache/FaultHidingSink.java
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okio.Buffer;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class FaultHidingSink extends ForwardingSink {
|
||||
private boolean hasErrors;
|
||||
|
||||
FaultHidingSink(Sink sink) {
|
||||
super(sink);
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.hasErrors) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.close();
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink, java.io.Flushable
|
||||
public void flush() throws IOException {
|
||||
if (this.hasErrors) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.flush();
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onException(IOException iOException) {
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
if (this.hasErrors) {
|
||||
buffer.skip(j);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.write(buffer, j);
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
sources/okhttp3/internal/cache/InternalCache.java
vendored
Normal file
20
sources/okhttp3/internal/cache/InternalCache.java
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface InternalCache {
|
||||
Response get(Request request) throws IOException;
|
||||
|
||||
CacheRequest put(Response response) throws IOException;
|
||||
|
||||
void remove(Request request) throws IOException;
|
||||
|
||||
void trackConditionalCacheHit();
|
||||
|
||||
void trackResponse(CacheStrategy cacheStrategy);
|
||||
|
||||
void update(Response response, Response response2);
|
||||
}
|
||||
38
sources/okhttp3/internal/cache2/FileOperator.java
Normal file
38
sources/okhttp3/internal/cache2/FileOperator.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package okhttp3.internal.cache2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import okio.Buffer;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class FileOperator {
|
||||
private final FileChannel fileChannel;
|
||||
|
||||
FileOperator(FileChannel fileChannel) {
|
||||
this.fileChannel = fileChannel;
|
||||
}
|
||||
|
||||
public void read(long j, Buffer buffer, long j2) throws IOException {
|
||||
if (j2 < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
while (j2 > 0) {
|
||||
long transferTo = this.fileChannel.transferTo(j, j2, buffer);
|
||||
j += transferTo;
|
||||
j2 -= transferTo;
|
||||
}
|
||||
}
|
||||
|
||||
public void write(long j, Buffer buffer, long j2) throws IOException {
|
||||
if (j2 < 0 || j2 > buffer.size()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
long j3 = j;
|
||||
long j4 = j2;
|
||||
while (j4 > 0) {
|
||||
long transferFrom = this.fileChannel.transferFrom(buffer, j3, j4);
|
||||
j3 += transferFrom;
|
||||
j4 -= transferFrom;
|
||||
}
|
||||
}
|
||||
}
|
||||
274
sources/okhttp3/internal/cache2/Relay.java
Normal file
274
sources/okhttp3/internal/cache2/Relay.java
Normal file
@@ -0,0 +1,274 @@
|
||||
package okhttp3.internal.cache2;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.Buffer;
|
||||
import okio.ByteString;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class Relay {
|
||||
private static final long FILE_HEADER_SIZE = 32;
|
||||
static final ByteString PREFIX_CLEAN = ByteString.encodeUtf8("OkHttp cache v1\n");
|
||||
static final ByteString PREFIX_DIRTY = ByteString.encodeUtf8("OkHttp DIRTY :(\n");
|
||||
private static final int SOURCE_FILE = 2;
|
||||
private static final int SOURCE_UPSTREAM = 1;
|
||||
final long bufferMaxSize;
|
||||
boolean complete;
|
||||
RandomAccessFile file;
|
||||
private final ByteString metadata;
|
||||
int sourceCount;
|
||||
Source upstream;
|
||||
long upstreamPos;
|
||||
Thread upstreamReader;
|
||||
final Buffer upstreamBuffer = new Buffer();
|
||||
final Buffer buffer = new Buffer();
|
||||
|
||||
class RelaySource implements Source {
|
||||
private FileOperator fileOperator;
|
||||
private long sourcePos;
|
||||
private final Timeout timeout = new Timeout();
|
||||
|
||||
RelaySource() {
|
||||
this.fileOperator = new FileOperator(Relay.this.file.getChannel());
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.fileOperator == null) {
|
||||
return;
|
||||
}
|
||||
RandomAccessFile randomAccessFile = null;
|
||||
this.fileOperator = null;
|
||||
synchronized (Relay.this) {
|
||||
Relay relay = Relay.this;
|
||||
relay.sourceCount--;
|
||||
if (Relay.this.sourceCount == 0) {
|
||||
RandomAccessFile randomAccessFile2 = Relay.this.file;
|
||||
Relay.this.file = null;
|
||||
randomAccessFile = randomAccessFile2;
|
||||
}
|
||||
}
|
||||
if (randomAccessFile != null) {
|
||||
Util.closeQuietly(randomAccessFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:18:0x004d, code lost:
|
||||
|
||||
if (r5 != 2) goto L26;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:19:0x004f, code lost:
|
||||
|
||||
r2 = java.lang.Math.min(r23, r7 - r21.sourcePos);
|
||||
r21.fileOperator.read(r21.sourcePos + 32, r22, r2);
|
||||
r21.sourcePos += r2;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:20:0x0068, code lost:
|
||||
|
||||
return r2;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:24:0x006a, code lost:
|
||||
|
||||
r5 = r21.this$0.upstream.read(r21.this$0.upstreamBuffer, r21.this$0.bufferMaxSize);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:25:0x007c, code lost:
|
||||
|
||||
if (r5 != (-1)) goto L38;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:26:0x007e, code lost:
|
||||
|
||||
r21.this$0.commit(r7);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:27:0x0083, code lost:
|
||||
|
||||
r2 = r21.this$0;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:28:0x0085, code lost:
|
||||
|
||||
monitor-enter(r2);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:30:0x0086, code lost:
|
||||
|
||||
r21.this$0.upstreamReader = null;
|
||||
r21.this$0.notifyAll();
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:31:0x008f, code lost:
|
||||
|
||||
monitor-exit(r2);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:32:0x0090, code lost:
|
||||
|
||||
return -1;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:37:0x0094, code lost:
|
||||
|
||||
r2 = java.lang.Math.min(r5, r23);
|
||||
r21.this$0.upstreamBuffer.copyTo(r22, 0, r2);
|
||||
r21.sourcePos += r2;
|
||||
r21.fileOperator.write(r7 + 32, r21.this$0.upstreamBuffer.clone(), r5);
|
||||
r7 = r21.this$0;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:38:0x00bd, code lost:
|
||||
|
||||
monitor-enter(r7);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:40:0x00be, code lost:
|
||||
|
||||
r21.this$0.buffer.write(r21.this$0.upstreamBuffer, r5);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:41:0x00d7, code lost:
|
||||
|
||||
if (r21.this$0.buffer.size() <= r21.this$0.bufferMaxSize) goto L43;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:42:0x00d9, code lost:
|
||||
|
||||
r21.this$0.buffer.skip(r21.this$0.buffer.size() - r21.this$0.bufferMaxSize);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:43:0x00ed, code lost:
|
||||
|
||||
r21.this$0.upstreamPos += r5;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:44:0x00f4, code lost:
|
||||
|
||||
monitor-exit(r7);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:45:0x00f5, code lost:
|
||||
|
||||
r5 = r21.this$0;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:46:0x00f7, code lost:
|
||||
|
||||
monitor-enter(r5);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:48:0x00f8, code lost:
|
||||
|
||||
r21.this$0.upstreamReader = null;
|
||||
r21.this$0.notifyAll();
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:49:0x0101, code lost:
|
||||
|
||||
monitor-exit(r5);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:50:0x0102, code lost:
|
||||
|
||||
return r2;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:59:0x0109, code lost:
|
||||
|
||||
r0 = move-exception;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:61:0x010c, code lost:
|
||||
|
||||
monitor-enter(r21.this$0);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:63:0x010d, code lost:
|
||||
|
||||
r21.this$0.upstreamReader = null;
|
||||
r21.this$0.notifyAll();
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:65:0x0117, code lost:
|
||||
|
||||
throw r0;
|
||||
*/
|
||||
@Override // okio.Source
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public long read(okio.Buffer r22, long r23) throws java.io.IOException {
|
||||
/*
|
||||
Method dump skipped, instructions count: 322
|
||||
To view this dump change 'Code comments level' option to 'DEBUG'
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.cache2.Relay.RelaySource.read(okio.Buffer, long):long");
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
}
|
||||
|
||||
private Relay(RandomAccessFile randomAccessFile, Source source, long j, ByteString byteString, long j2) {
|
||||
this.file = randomAccessFile;
|
||||
this.upstream = source;
|
||||
this.complete = source == null;
|
||||
this.upstreamPos = j;
|
||||
this.metadata = byteString;
|
||||
this.bufferMaxSize = j2;
|
||||
}
|
||||
|
||||
public static Relay edit(File file, Source source, ByteString byteString, long j) throws IOException {
|
||||
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
||||
Relay relay = new Relay(randomAccessFile, source, 0L, byteString, j);
|
||||
randomAccessFile.setLength(0L);
|
||||
relay.writeHeader(PREFIX_DIRTY, -1L, -1L);
|
||||
return relay;
|
||||
}
|
||||
|
||||
public static Relay read(File file) throws IOException {
|
||||
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
||||
FileOperator fileOperator = new FileOperator(randomAccessFile.getChannel());
|
||||
Buffer buffer = new Buffer();
|
||||
fileOperator.read(0L, buffer, 32L);
|
||||
if (!buffer.readByteString(PREFIX_CLEAN.size()).equals(PREFIX_CLEAN)) {
|
||||
throw new IOException("unreadable cache file");
|
||||
}
|
||||
long readLong = buffer.readLong();
|
||||
long readLong2 = buffer.readLong();
|
||||
Buffer buffer2 = new Buffer();
|
||||
fileOperator.read(readLong + 32, buffer2, readLong2);
|
||||
return new Relay(randomAccessFile, null, readLong, buffer2.readByteString(), 0L);
|
||||
}
|
||||
|
||||
private void writeHeader(ByteString byteString, long j, long j2) throws IOException {
|
||||
Buffer buffer = new Buffer();
|
||||
buffer.write(byteString);
|
||||
buffer.writeLong(j);
|
||||
buffer.writeLong(j2);
|
||||
if (buffer.size() != 32) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
new FileOperator(this.file.getChannel()).write(0L, buffer, 32L);
|
||||
}
|
||||
|
||||
private void writeMetadata(long j) throws IOException {
|
||||
Buffer buffer = new Buffer();
|
||||
buffer.write(this.metadata);
|
||||
new FileOperator(this.file.getChannel()).write(32 + j, buffer, this.metadata.size());
|
||||
}
|
||||
|
||||
void commit(long j) throws IOException {
|
||||
writeMetadata(j);
|
||||
this.file.getChannel().force(false);
|
||||
writeHeader(PREFIX_CLEAN, j, this.metadata.size());
|
||||
this.file.getChannel().force(false);
|
||||
synchronized (this) {
|
||||
this.complete = true;
|
||||
}
|
||||
Util.closeQuietly(this.upstream);
|
||||
this.upstream = null;
|
||||
}
|
||||
|
||||
boolean isClosed() {
|
||||
return this.file == null;
|
||||
}
|
||||
|
||||
public ByteString metadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
public Source newSource() {
|
||||
synchronized (this) {
|
||||
if (this.file == null) {
|
||||
return null;
|
||||
}
|
||||
this.sourceCount++;
|
||||
return new RelaySource();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
sources/okhttp3/internal/connection/ConnectInterceptor.java
Normal file
25
sources/okhttp3/internal/connection/ConnectInterceptor.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.http.RealInterceptorChain;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class ConnectInterceptor implements Interceptor {
|
||||
public final OkHttpClient client;
|
||||
|
||||
public ConnectInterceptor(OkHttpClient okHttpClient) {
|
||||
this.client = okHttpClient;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
RealInterceptorChain realInterceptorChain = (RealInterceptorChain) chain;
|
||||
Request request = realInterceptorChain.request();
|
||||
StreamAllocation streamAllocation = realInterceptorChain.streamAllocation();
|
||||
return realInterceptorChain.proceed(request, streamAllocation, streamAllocation.newStream(this.client, chain, !request.method().equals("GET")), streamAllocation.connection());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.UnknownServiceException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLProtocolException;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.internal.Internal;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class ConnectionSpecSelector {
|
||||
private final List<ConnectionSpec> connectionSpecs;
|
||||
private boolean isFallback;
|
||||
private boolean isFallbackPossible;
|
||||
private int nextModeIndex = 0;
|
||||
|
||||
public ConnectionSpecSelector(List<ConnectionSpec> list) {
|
||||
this.connectionSpecs = list;
|
||||
}
|
||||
|
||||
private boolean isFallbackPossible(SSLSocket sSLSocket) {
|
||||
for (int i = this.nextModeIndex; i < this.connectionSpecs.size(); i++) {
|
||||
if (this.connectionSpecs.get(i).isCompatible(sSLSocket)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ConnectionSpec configureSecureSocket(SSLSocket sSLSocket) throws IOException {
|
||||
ConnectionSpec connectionSpec;
|
||||
int i = this.nextModeIndex;
|
||||
int size = this.connectionSpecs.size();
|
||||
while (true) {
|
||||
if (i >= size) {
|
||||
connectionSpec = null;
|
||||
break;
|
||||
}
|
||||
connectionSpec = this.connectionSpecs.get(i);
|
||||
if (connectionSpec.isCompatible(sSLSocket)) {
|
||||
this.nextModeIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (connectionSpec != null) {
|
||||
this.isFallbackPossible = isFallbackPossible(sSLSocket);
|
||||
Internal.instance.apply(connectionSpec, sSLSocket, this.isFallback);
|
||||
return connectionSpec;
|
||||
}
|
||||
throw new UnknownServiceException("Unable to find acceptable protocols. isFallback=" + this.isFallback + ", modes=" + this.connectionSpecs + ", supported protocols=" + Arrays.toString(sSLSocket.getEnabledProtocols()));
|
||||
}
|
||||
|
||||
public boolean connectionFailed(IOException iOException) {
|
||||
this.isFallback = true;
|
||||
if (!this.isFallbackPossible || (iOException instanceof ProtocolException) || (iOException instanceof InterruptedIOException)) {
|
||||
return false;
|
||||
}
|
||||
boolean z = iOException instanceof SSLHandshakeException;
|
||||
if ((z && (iOException.getCause() instanceof CertificateException)) || (iOException instanceof SSLPeerUnverifiedException)) {
|
||||
return false;
|
||||
}
|
||||
return z || (iOException instanceof SSLProtocolException);
|
||||
}
|
||||
}
|
||||
391
sources/okhttp3/internal/connection/RealConnection.java
Normal file
391
sources/okhttp3/internal/connection/RealConnection.java
Normal file
@@ -0,0 +1,391 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import com.ubt.jimu.transport.model.TransportFile;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
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.ConnectionPool;
|
||||
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.HttpCodec;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.http1.Http1Codec;
|
||||
import okhttp3.internal.http2.ErrorCode;
|
||||
import okhttp3.internal.http2.Http2Codec;
|
||||
import okhttp3.internal.http2.Http2Connection;
|
||||
import okhttp3.internal.http2.Http2Stream;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okhttp3.internal.tls.OkHostnameVerifier;
|
||||
import okhttp3.internal.ws.RealWebSocket;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RealConnection extends Http2Connection.Listener implements Connection {
|
||||
private static final int MAX_TUNNEL_ATTEMPTS = 21;
|
||||
private static final String NPE_THROW_WITH_NULL = "throw with null exception";
|
||||
private final ConnectionPool connectionPool;
|
||||
private Handshake handshake;
|
||||
private Http2Connection http2Connection;
|
||||
public boolean noNewStreams;
|
||||
private Protocol protocol;
|
||||
private Socket rawSocket;
|
||||
private final Route route;
|
||||
private BufferedSink sink;
|
||||
private Socket socket;
|
||||
private BufferedSource source;
|
||||
public int successCount;
|
||||
public int allocationLimit = 1;
|
||||
public final List<Reference<StreamAllocation>> allocations = new ArrayList();
|
||||
public long idleAtNanos = Long.MAX_VALUE;
|
||||
|
||||
public RealConnection(ConnectionPool connectionPool, Route route) {
|
||||
this.connectionPool = connectionPool;
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
private void connectSocket(int i, int i2, Call call, EventListener eventListener) throws IOException {
|
||||
Proxy proxy = this.route.proxy();
|
||||
this.rawSocket = (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.HTTP) ? this.route.address().socketFactory().createSocket() : new Socket(proxy);
|
||||
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 (NPE_THROW_WITH_NULL.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;
|
||||
}
|
||||
}
|
||||
|
||||
private void connectTls(ConnectionSpecSelector connectionSpecSelector) throws IOException {
|
||||
SSLSocket sSLSocket;
|
||||
Address address = this.route.address();
|
||||
try {
|
||||
try {
|
||||
sSLSocket = (SSLSocket) address.sslSocketFactory().createSocket(this.rawSocket, address.url().host(), address.url().port(), true);
|
||||
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)) {
|
||||
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(this.socket));
|
||||
this.sink = Okio.buffer(Okio.sink(this.socket));
|
||||
this.handshake = handshake;
|
||||
this.protocol = selectedProtocol != null ? Protocol.get(selectedProtocol) : Protocol.HTTP_1_1;
|
||||
if (sSLSocket != null) {
|
||||
Platform.get().afterHandshake(sSLSocket);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
X509Certificate x509Certificate = (X509Certificate) handshake.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));
|
||||
} catch (AssertionError e) {
|
||||
e = e;
|
||||
if (!Util.isAndroidGetsocknameError(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new IOException(e);
|
||||
} catch (Throwable th) {
|
||||
th = th;
|
||||
if (sSLSocket != null) {
|
||||
Platform.get().afterHandshake(sSLSocket);
|
||||
}
|
||||
Util.closeQuietly((Socket) sSLSocket);
|
||||
throw th;
|
||||
}
|
||||
} catch (Throwable th2) {
|
||||
th = th2;
|
||||
sSLSocket = null;
|
||||
}
|
||||
} catch (AssertionError e2) {
|
||||
e = e2;
|
||||
}
|
||||
}
|
||||
|
||||
private void connectTunnel(int i, int i2, int i3, Call call, EventListener eventListener) throws IOException {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private Request createTunnel(int i, int i2, Request request, HttpUrl httpUrl) throws IOException {
|
||||
String str = "CONNECT " + Util.hostHeader(httpUrl, true) + " HTTP/1.1";
|
||||
while (true) {
|
||||
Http1Codec http1Codec = new Http1Codec(null, null, this.source, this.sink);
|
||||
this.source.timeout().timeout(i, TimeUnit.MILLISECONDS);
|
||||
this.sink.timeout().timeout(i2, TimeUnit.MILLISECONDS);
|
||||
http1Codec.writeRequest(request.headers(), str);
|
||||
http1Codec.finishRequest();
|
||||
Response build = http1Codec.readResponseHeaders(false).request(request).build();
|
||||
long contentLength = HttpHeaders.contentLength(build);
|
||||
if (contentLength == -1) {
|
||||
contentLength = 0;
|
||||
}
|
||||
Source newFixedLengthSource = http1Codec.newFixedLengthSource(contentLength);
|
||||
Util.skipAll(newFixedLengthSource, Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
newFixedLengthSource.close();
|
||||
int code = build.code();
|
||||
if (code == 200) {
|
||||
if (this.source.buffer().exhausted() && this.sink.buffer().exhausted()) {
|
||||
return null;
|
||||
}
|
||||
throw new IOException("TLS tunnel buffered too many bytes!");
|
||||
}
|
||||
if (code != 407) {
|
||||
throw new IOException("Unexpected response code for CONNECT: " + build.code());
|
||||
}
|
||||
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("Connection"))) {
|
||||
return authenticate;
|
||||
}
|
||||
request = authenticate;
|
||||
}
|
||||
}
|
||||
|
||||
private Request createTunnelRequest() {
|
||||
return new Request.Builder().url(this.route.address().url()).header("Host", Util.hostHeader(this.route.address().url(), true)).header("Proxy-Connection", "Keep-Alive").header("User-Agent", Version.userAgent()).build();
|
||||
}
|
||||
|
||||
private void establishProtocol(ConnectionSpecSelector connectionSpecSelector, int i, Call call, EventListener eventListener) throws IOException {
|
||||
if (this.route.address().sslSocketFactory() != null) {
|
||||
eventListener.secureConnectStart(call);
|
||||
connectTls(connectionSpecSelector);
|
||||
eventListener.secureConnectEnd(call, this.handshake);
|
||||
if (this.protocol == Protocol.HTTP_2) {
|
||||
startHttp2(i);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!this.route.address().protocols().contains(Protocol.H2_PRIOR_KNOWLEDGE)) {
|
||||
this.socket = this.rawSocket;
|
||||
this.protocol = Protocol.HTTP_1_1;
|
||||
} else {
|
||||
this.socket = this.rawSocket;
|
||||
this.protocol = Protocol.H2_PRIOR_KNOWLEDGE;
|
||||
startHttp2(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void startHttp2(int i) throws IOException {
|
||||
this.socket.setSoTimeout(0);
|
||||
this.http2Connection = new Http2Connection.Builder(true).socket(this.socket, this.route.address().url().host(), this.source, this.sink).listener(this).pingIntervalMillis(i).build();
|
||||
this.http2Connection.start();
|
||||
}
|
||||
|
||||
public static RealConnection testConnection(ConnectionPool connectionPool, Route route, Socket socket, long j) {
|
||||
RealConnection realConnection = new RealConnection(connectionPool, route);
|
||||
realConnection.socket = socket;
|
||||
realConnection.idleAtNanos = j;
|
||||
return realConnection;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
Util.closeQuietly(this.rawSocket);
|
||||
}
|
||||
|
||||
/* JADX WARN: Removed duplicated region for block: B:32:0x00e4 */
|
||||
/* JADX WARN: Removed duplicated region for block: B:43:0x00f4 A[ORIG_RETURN, RETURN] */
|
||||
/* JADX WARN: Removed duplicated region for block: B:47:0x012f */
|
||||
/* JADX WARN: Removed duplicated region for block: B:49:0x013b */
|
||||
/* JADX WARN: Removed duplicated region for block: B:54:0x0143 A[SYNTHETIC] */
|
||||
/* JADX WARN: Removed duplicated region for block: B:56:0x0136 */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public void connect(int r17, int r18, int r19, int r20, boolean r21, okhttp3.Call r22, okhttp3.EventListener r23) {
|
||||
/*
|
||||
Method dump skipped, instructions count: 345
|
||||
To view this dump change 'Code comments level' option to 'DEBUG'
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.connection.RealConnection.connect(int, int, int, int, boolean, okhttp3.Call, okhttp3.EventListener):void");
|
||||
}
|
||||
|
||||
@Override // okhttp3.Connection
|
||||
public Handshake handshake() {
|
||||
return this.handshake;
|
||||
}
|
||||
|
||||
public boolean isEligible(Address address, Route route) {
|
||||
if (this.allocations.size() >= this.allocationLimit || this.noNewStreams || !Internal.instance.equalsNonHost(this.route.address(), address)) {
|
||||
return false;
|
||||
}
|
||||
if (address.url().host().equals(route().address().url().host())) {
|
||||
return true;
|
||||
}
|
||||
if (this.http2Connection == null || route == null || route.proxy().type() != Proxy.Type.DIRECT || this.route.proxy().type() != Proxy.Type.DIRECT || !this.route.socketAddress().equals(route.socketAddress()) || route.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 boolean isHealthy(boolean z) {
|
||||
if (this.socket.isClosed() || this.socket.isInputShutdown() || this.socket.isOutputShutdown()) {
|
||||
return false;
|
||||
}
|
||||
if (this.http2Connection != null) {
|
||||
return !r0.isShutdown();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isMultiplexed() {
|
||||
return this.http2Connection != null;
|
||||
}
|
||||
|
||||
public HttpCodec newCodec(OkHttpClient okHttpClient, Interceptor.Chain chain, StreamAllocation streamAllocation) throws SocketException {
|
||||
Http2Connection http2Connection = this.http2Connection;
|
||||
if (http2Connection != null) {
|
||||
return new Http2Codec(okHttpClient, chain, streamAllocation, http2Connection);
|
||||
}
|
||||
this.socket.setSoTimeout(chain.readTimeoutMillis());
|
||||
this.source.timeout().timeout(chain.readTimeoutMillis(), TimeUnit.MILLISECONDS);
|
||||
this.sink.timeout().timeout(chain.writeTimeoutMillis(), TimeUnit.MILLISECONDS);
|
||||
return new Http1Codec(okHttpClient, streamAllocation, this.source, this.sink);
|
||||
}
|
||||
|
||||
public RealWebSocket.Streams newWebSocketStreams(final StreamAllocation streamAllocation) {
|
||||
return new RealWebSocket.Streams(true, this.source, this.sink) { // from class: okhttp3.internal.connection.RealConnection.1
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
StreamAllocation streamAllocation2 = streamAllocation;
|
||||
streamAllocation2.streamFinished(true, streamAllocation2.codec(), -1L, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Connection.Listener
|
||||
public void onSettings(Http2Connection http2Connection) {
|
||||
synchronized (this.connectionPool) {
|
||||
this.allocationLimit = http2Connection.maxConcurrentStreams();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Connection.Listener
|
||||
public void onStream(Http2Stream http2Stream) throws IOException {
|
||||
http2Stream.close(ErrorCode.REFUSED_STREAM);
|
||||
}
|
||||
|
||||
@Override // okhttp3.Connection
|
||||
public Protocol protocol() {
|
||||
return this.protocol;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Connection
|
||||
public Route route() {
|
||||
return this.route;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Connection
|
||||
public Socket socket() {
|
||||
return this.socket;
|
||||
}
|
||||
|
||||
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 String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Connection{");
|
||||
sb.append(this.route.address().url().host());
|
||||
sb.append(":");
|
||||
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() : TransportFile.TYPE_NONE);
|
||||
sb.append(" protocol=");
|
||||
sb.append(this.protocol);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
22
sources/okhttp3/internal/connection/RouteDatabase.java
Normal file
22
sources/okhttp3/internal/connection/RouteDatabase.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import okhttp3.Route;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RouteDatabase {
|
||||
private final Set<Route> failedRoutes = new LinkedHashSet();
|
||||
|
||||
public synchronized void connected(Route route) {
|
||||
this.failedRoutes.remove(route);
|
||||
}
|
||||
|
||||
public synchronized void failed(Route route) {
|
||||
this.failedRoutes.add(route);
|
||||
}
|
||||
|
||||
public synchronized boolean shouldPostpone(Route route) {
|
||||
return this.failedRoutes.contains(route);
|
||||
}
|
||||
}
|
||||
29
sources/okhttp3/internal/connection/RouteException.java
Normal file
29
sources/okhttp3/internal/connection/RouteException.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RouteException extends RuntimeException {
|
||||
private IOException firstException;
|
||||
private IOException lastException;
|
||||
|
||||
public RouteException(IOException iOException) {
|
||||
super(iOException);
|
||||
this.firstException = iOException;
|
||||
this.lastException = iOException;
|
||||
}
|
||||
|
||||
public void addConnectException(IOException iOException) {
|
||||
Util.addSuppressedIfPossible(this.firstException, iOException);
|
||||
this.lastException = iOException;
|
||||
}
|
||||
|
||||
public IOException getFirstConnectException() {
|
||||
return this.firstException;
|
||||
}
|
||||
|
||||
public IOException getLastConnectException() {
|
||||
return this.lastException;
|
||||
}
|
||||
}
|
||||
170
sources/okhttp3/internal/connection/RouteSelector.java
Normal file
170
sources/okhttp3/internal/connection/RouteSelector.java
Normal file
@@ -0,0 +1,170 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import okhttp3.Address;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.EventListener;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Route;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RouteSelector {
|
||||
private final Address address;
|
||||
private final Call call;
|
||||
private final EventListener eventListener;
|
||||
private int nextProxyIndex;
|
||||
private final RouteDatabase routeDatabase;
|
||||
private List<Proxy> proxies = Collections.emptyList();
|
||||
private List<InetSocketAddress> inetSocketAddresses = Collections.emptyList();
|
||||
private final List<Route> postponedRoutes = new ArrayList();
|
||||
|
||||
public static final class Selection {
|
||||
private int nextRouteIndex = 0;
|
||||
private final List<Route> routes;
|
||||
|
||||
Selection(List<Route> list) {
|
||||
this.routes = list;
|
||||
}
|
||||
|
||||
public List<Route> getAll() {
|
||||
return new ArrayList(this.routes);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return this.nextRouteIndex < this.routes.size();
|
||||
}
|
||||
|
||||
public Route next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
List<Route> list = this.routes;
|
||||
int i = this.nextRouteIndex;
|
||||
this.nextRouteIndex = i + 1;
|
||||
return list.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
public RouteSelector(Address address, RouteDatabase routeDatabase, Call call, EventListener eventListener) {
|
||||
this.address = address;
|
||||
this.routeDatabase = routeDatabase;
|
||||
this.call = call;
|
||||
this.eventListener = eventListener;
|
||||
resetNextProxy(address.url(), address.proxy());
|
||||
}
|
||||
|
||||
static String getHostString(InetSocketAddress inetSocketAddress) {
|
||||
InetAddress address = inetSocketAddress.getAddress();
|
||||
return address == null ? inetSocketAddress.getHostName() : address.getHostAddress();
|
||||
}
|
||||
|
||||
private boolean hasNextProxy() {
|
||||
return this.nextProxyIndex < this.proxies.size();
|
||||
}
|
||||
|
||||
private Proxy nextProxy() throws IOException {
|
||||
if (hasNextProxy()) {
|
||||
List<Proxy> list = this.proxies;
|
||||
int i = this.nextProxyIndex;
|
||||
this.nextProxyIndex = i + 1;
|
||||
Proxy proxy = list.get(i);
|
||||
resetNextInetSocketAddress(proxy);
|
||||
return proxy;
|
||||
}
|
||||
throw new SocketException("No route to " + this.address.url().host() + "; exhausted proxy configurations: " + this.proxies);
|
||||
}
|
||||
|
||||
private void resetNextInetSocketAddress(Proxy proxy) throws IOException {
|
||||
String host;
|
||||
int port;
|
||||
this.inetSocketAddresses = new ArrayList();
|
||||
if (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.SOCKS) {
|
||||
host = this.address.url().host();
|
||||
port = this.address.url().port();
|
||||
} else {
|
||||
SocketAddress address = proxy.address();
|
||||
if (!(address instanceof InetSocketAddress)) {
|
||||
throw new IllegalArgumentException("Proxy.address() is not an InetSocketAddress: " + address.getClass());
|
||||
}
|
||||
InetSocketAddress inetSocketAddress = (InetSocketAddress) address;
|
||||
host = getHostString(inetSocketAddress);
|
||||
port = inetSocketAddress.getPort();
|
||||
}
|
||||
if (port < 1 || port > 65535) {
|
||||
throw new SocketException("No route to " + host + ":" + port + "; port is out of range");
|
||||
}
|
||||
if (proxy.type() == Proxy.Type.SOCKS) {
|
||||
this.inetSocketAddresses.add(InetSocketAddress.createUnresolved(host, port));
|
||||
return;
|
||||
}
|
||||
this.eventListener.dnsStart(this.call, host);
|
||||
List<InetAddress> lookup = this.address.dns().lookup(host);
|
||||
if (lookup.isEmpty()) {
|
||||
throw new UnknownHostException(this.address.dns() + " returned no addresses for " + host);
|
||||
}
|
||||
this.eventListener.dnsEnd(this.call, host, lookup);
|
||||
int size = lookup.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
this.inetSocketAddresses.add(new InetSocketAddress(lookup.get(i), port));
|
||||
}
|
||||
}
|
||||
|
||||
private void resetNextProxy(HttpUrl httpUrl, Proxy proxy) {
|
||||
if (proxy != null) {
|
||||
this.proxies = Collections.singletonList(proxy);
|
||||
} else {
|
||||
List<Proxy> select = this.address.proxySelector().select(httpUrl.uri());
|
||||
this.proxies = (select == null || select.isEmpty()) ? Util.immutableList(Proxy.NO_PROXY) : Util.immutableList(select);
|
||||
}
|
||||
this.nextProxyIndex = 0;
|
||||
}
|
||||
|
||||
public void connectFailed(Route route, IOException iOException) {
|
||||
if (route.proxy().type() != Proxy.Type.DIRECT && this.address.proxySelector() != null) {
|
||||
this.address.proxySelector().connectFailed(this.address.url().uri(), route.proxy().address(), iOException);
|
||||
}
|
||||
this.routeDatabase.failed(route);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return hasNextProxy() || !this.postponedRoutes.isEmpty();
|
||||
}
|
||||
|
||||
public Selection next() throws IOException {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
ArrayList arrayList = new ArrayList();
|
||||
while (hasNextProxy()) {
|
||||
Proxy nextProxy = nextProxy();
|
||||
int size = this.inetSocketAddresses.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Route route = new Route(this.address, nextProxy, this.inetSocketAddresses.get(i));
|
||||
if (this.routeDatabase.shouldPostpone(route)) {
|
||||
this.postponedRoutes.add(route);
|
||||
} else {
|
||||
arrayList.add(route);
|
||||
}
|
||||
}
|
||||
if (!arrayList.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arrayList.isEmpty()) {
|
||||
arrayList.addAll(this.postponedRoutes);
|
||||
this.postponedRoutes.clear();
|
||||
}
|
||||
return new Selection(arrayList);
|
||||
}
|
||||
}
|
||||
427
sources/okhttp3/internal/connection/StreamAllocation.java
Normal file
427
sources/okhttp3/internal/connection/StreamAllocation.java
Normal file
@@ -0,0 +1,427 @@
|
||||
package okhttp3.internal.connection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import okhttp3.Address;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.EventListener;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Route;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.RouteSelector;
|
||||
import okhttp3.internal.http.HttpCodec;
|
||||
import okhttp3.internal.http2.ConnectionShutdownException;
|
||||
import okhttp3.internal.http2.ErrorCode;
|
||||
import okhttp3.internal.http2.StreamResetException;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class StreamAllocation {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
public final Address address;
|
||||
public final Call call;
|
||||
private final Object callStackTrace;
|
||||
private boolean canceled;
|
||||
private HttpCodec codec;
|
||||
private RealConnection connection;
|
||||
private final ConnectionPool connectionPool;
|
||||
public final EventListener eventListener;
|
||||
private int refusedStreamCount;
|
||||
private boolean released;
|
||||
private boolean reportedAcquired;
|
||||
private Route route;
|
||||
private RouteSelector.Selection routeSelection;
|
||||
private final RouteSelector routeSelector;
|
||||
|
||||
public static final class StreamAllocationReference extends WeakReference<StreamAllocation> {
|
||||
public final Object callStackTrace;
|
||||
|
||||
StreamAllocationReference(StreamAllocation streamAllocation, Object obj) {
|
||||
super(streamAllocation);
|
||||
this.callStackTrace = obj;
|
||||
}
|
||||
}
|
||||
|
||||
public StreamAllocation(ConnectionPool connectionPool, Address address, Call call, EventListener eventListener, Object obj) {
|
||||
this.connectionPool = connectionPool;
|
||||
this.address = address;
|
||||
this.call = call;
|
||||
this.eventListener = eventListener;
|
||||
this.routeSelector = new RouteSelector(address, routeDatabase(), call, eventListener);
|
||||
this.callStackTrace = obj;
|
||||
}
|
||||
|
||||
private Socket deallocate(boolean z, boolean z2, boolean z3) {
|
||||
Socket socket;
|
||||
if (z3) {
|
||||
this.codec = null;
|
||||
}
|
||||
if (z2) {
|
||||
this.released = true;
|
||||
}
|
||||
RealConnection realConnection = this.connection;
|
||||
if (realConnection != null) {
|
||||
if (z) {
|
||||
realConnection.noNewStreams = true;
|
||||
}
|
||||
if (this.codec == null && (this.released || this.connection.noNewStreams)) {
|
||||
release(this.connection);
|
||||
if (this.connection.allocations.isEmpty()) {
|
||||
this.connection.idleAtNanos = System.nanoTime();
|
||||
if (Internal.instance.connectionBecameIdle(this.connectionPool, this.connection)) {
|
||||
socket = this.connection.socket();
|
||||
this.connection = null;
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
socket = null;
|
||||
this.connection = null;
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private RealConnection findConnection(int i, int i2, int i3, int i4, boolean z) throws IOException {
|
||||
Socket releaseIfNoNewStreams;
|
||||
Socket socket;
|
||||
RealConnection realConnection;
|
||||
RealConnection realConnection2;
|
||||
RealConnection realConnection3;
|
||||
Route route;
|
||||
boolean z2;
|
||||
boolean z3;
|
||||
RouteSelector.Selection selection;
|
||||
synchronized (this.connectionPool) {
|
||||
if (this.released) {
|
||||
throw new IllegalStateException("released");
|
||||
}
|
||||
if (this.codec != null) {
|
||||
throw new IllegalStateException("codec != null");
|
||||
}
|
||||
if (this.canceled) {
|
||||
throw new IOException("Canceled");
|
||||
}
|
||||
RealConnection realConnection4 = this.connection;
|
||||
releaseIfNoNewStreams = releaseIfNoNewStreams();
|
||||
socket = null;
|
||||
if (this.connection != null) {
|
||||
realConnection2 = this.connection;
|
||||
realConnection = null;
|
||||
} else {
|
||||
realConnection = realConnection4;
|
||||
realConnection2 = null;
|
||||
}
|
||||
if (!this.reportedAcquired) {
|
||||
realConnection = null;
|
||||
}
|
||||
if (realConnection2 == null) {
|
||||
Internal.instance.get(this.connectionPool, this.address, this, null);
|
||||
if (this.connection != null) {
|
||||
realConnection3 = this.connection;
|
||||
route = null;
|
||||
z2 = true;
|
||||
} else {
|
||||
route = this.route;
|
||||
realConnection3 = realConnection2;
|
||||
}
|
||||
} else {
|
||||
realConnection3 = realConnection2;
|
||||
route = null;
|
||||
}
|
||||
z2 = false;
|
||||
}
|
||||
Util.closeQuietly(releaseIfNoNewStreams);
|
||||
if (realConnection != null) {
|
||||
this.eventListener.connectionReleased(this.call, realConnection);
|
||||
}
|
||||
if (z2) {
|
||||
this.eventListener.connectionAcquired(this.call, realConnection3);
|
||||
}
|
||||
if (realConnection3 != null) {
|
||||
return realConnection3;
|
||||
}
|
||||
if (route != null || ((selection = this.routeSelection) != null && selection.hasNext())) {
|
||||
z3 = false;
|
||||
} else {
|
||||
this.routeSelection = this.routeSelector.next();
|
||||
z3 = true;
|
||||
}
|
||||
synchronized (this.connectionPool) {
|
||||
if (this.canceled) {
|
||||
throw new IOException("Canceled");
|
||||
}
|
||||
if (z3) {
|
||||
List<Route> all = this.routeSelection.getAll();
|
||||
int size = all.size();
|
||||
int i5 = 0;
|
||||
while (true) {
|
||||
if (i5 >= size) {
|
||||
break;
|
||||
}
|
||||
Route route2 = all.get(i5);
|
||||
Internal.instance.get(this.connectionPool, this.address, this, route2);
|
||||
if (this.connection != null) {
|
||||
realConnection3 = this.connection;
|
||||
this.route = route2;
|
||||
z2 = true;
|
||||
break;
|
||||
}
|
||||
i5++;
|
||||
}
|
||||
}
|
||||
if (!z2) {
|
||||
if (route == null) {
|
||||
route = this.routeSelection.next();
|
||||
}
|
||||
this.route = route;
|
||||
this.refusedStreamCount = 0;
|
||||
realConnection3 = new RealConnection(this.connectionPool, route);
|
||||
acquire(realConnection3, false);
|
||||
}
|
||||
}
|
||||
if (z2) {
|
||||
this.eventListener.connectionAcquired(this.call, realConnection3);
|
||||
return realConnection3;
|
||||
}
|
||||
realConnection3.connect(i, i2, i3, i4, z, this.call, this.eventListener);
|
||||
routeDatabase().connected(realConnection3.route());
|
||||
synchronized (this.connectionPool) {
|
||||
this.reportedAcquired = true;
|
||||
Internal.instance.put(this.connectionPool, realConnection3);
|
||||
if (realConnection3.isMultiplexed()) {
|
||||
socket = Internal.instance.deduplicate(this.connectionPool, this.address, this);
|
||||
realConnection3 = this.connection;
|
||||
}
|
||||
}
|
||||
Util.closeQuietly(socket);
|
||||
this.eventListener.connectionAcquired(this.call, realConnection3);
|
||||
return realConnection3;
|
||||
}
|
||||
|
||||
private RealConnection findHealthyConnection(int i, int i2, int i3, int i4, boolean z, boolean z2) throws IOException {
|
||||
while (true) {
|
||||
RealConnection findConnection = findConnection(i, i2, i3, i4, z);
|
||||
synchronized (this.connectionPool) {
|
||||
if (findConnection.successCount == 0) {
|
||||
return findConnection;
|
||||
}
|
||||
if (findConnection.isHealthy(z2)) {
|
||||
return findConnection;
|
||||
}
|
||||
noNewStreams();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Socket releaseIfNoNewStreams() {
|
||||
RealConnection realConnection = this.connection;
|
||||
if (realConnection == null || !realConnection.noNewStreams) {
|
||||
return null;
|
||||
}
|
||||
return deallocate(false, false, true);
|
||||
}
|
||||
|
||||
private RouteDatabase routeDatabase() {
|
||||
return Internal.instance.routeDatabase(this.connectionPool);
|
||||
}
|
||||
|
||||
public void acquire(RealConnection realConnection, boolean z) {
|
||||
if (this.connection != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.connection = realConnection;
|
||||
this.reportedAcquired = z;
|
||||
realConnection.allocations.add(new StreamAllocationReference(this, this.callStackTrace));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
HttpCodec httpCodec;
|
||||
RealConnection realConnection;
|
||||
synchronized (this.connectionPool) {
|
||||
this.canceled = true;
|
||||
httpCodec = this.codec;
|
||||
realConnection = this.connection;
|
||||
}
|
||||
if (httpCodec != null) {
|
||||
httpCodec.cancel();
|
||||
} else if (realConnection != null) {
|
||||
realConnection.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public HttpCodec codec() {
|
||||
HttpCodec httpCodec;
|
||||
synchronized (this.connectionPool) {
|
||||
httpCodec = this.codec;
|
||||
}
|
||||
return httpCodec;
|
||||
}
|
||||
|
||||
public synchronized RealConnection connection() {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
public boolean hasMoreRoutes() {
|
||||
RouteSelector.Selection selection;
|
||||
return this.route != null || ((selection = this.routeSelection) != null && selection.hasNext()) || this.routeSelector.hasNext();
|
||||
}
|
||||
|
||||
public HttpCodec newStream(OkHttpClient okHttpClient, Interceptor.Chain chain, boolean z) {
|
||||
try {
|
||||
HttpCodec newCodec = findHealthyConnection(chain.connectTimeoutMillis(), chain.readTimeoutMillis(), chain.writeTimeoutMillis(), okHttpClient.pingIntervalMillis(), okHttpClient.retryOnConnectionFailure(), z).newCodec(okHttpClient, chain, this);
|
||||
synchronized (this.connectionPool) {
|
||||
this.codec = newCodec;
|
||||
}
|
||||
return newCodec;
|
||||
} catch (IOException e) {
|
||||
throw new RouteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void noNewStreams() {
|
||||
RealConnection realConnection;
|
||||
Socket deallocate;
|
||||
synchronized (this.connectionPool) {
|
||||
realConnection = this.connection;
|
||||
deallocate = deallocate(true, false, false);
|
||||
if (this.connection != null) {
|
||||
realConnection = null;
|
||||
}
|
||||
}
|
||||
Util.closeQuietly(deallocate);
|
||||
if (realConnection != null) {
|
||||
this.eventListener.connectionReleased(this.call, realConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
RealConnection realConnection;
|
||||
Socket deallocate;
|
||||
synchronized (this.connectionPool) {
|
||||
realConnection = this.connection;
|
||||
deallocate = deallocate(false, true, false);
|
||||
if (this.connection != null) {
|
||||
realConnection = null;
|
||||
}
|
||||
}
|
||||
Util.closeQuietly(deallocate);
|
||||
if (realConnection != null) {
|
||||
this.eventListener.connectionReleased(this.call, realConnection);
|
||||
this.eventListener.callEnd(this.call);
|
||||
}
|
||||
}
|
||||
|
||||
public Socket releaseAndAcquire(RealConnection realConnection) {
|
||||
if (this.codec != null || this.connection.allocations.size() != 1) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
Reference<StreamAllocation> reference = this.connection.allocations.get(0);
|
||||
Socket deallocate = deallocate(true, false, false);
|
||||
this.connection = realConnection;
|
||||
realConnection.allocations.add(reference);
|
||||
return deallocate;
|
||||
}
|
||||
|
||||
public Route route() {
|
||||
return this.route;
|
||||
}
|
||||
|
||||
public void streamFailed(IOException iOException) {
|
||||
boolean z;
|
||||
RealConnection realConnection;
|
||||
Socket deallocate;
|
||||
synchronized (this.connectionPool) {
|
||||
if (iOException instanceof StreamResetException) {
|
||||
ErrorCode errorCode = ((StreamResetException) iOException).errorCode;
|
||||
if (errorCode == ErrorCode.REFUSED_STREAM) {
|
||||
this.refusedStreamCount++;
|
||||
if (this.refusedStreamCount > 1) {
|
||||
this.route = null;
|
||||
z = true;
|
||||
}
|
||||
z = false;
|
||||
} else {
|
||||
if (errorCode != ErrorCode.CANCEL) {
|
||||
this.route = null;
|
||||
z = true;
|
||||
}
|
||||
z = false;
|
||||
}
|
||||
} else {
|
||||
if (this.connection != null && (!this.connection.isMultiplexed() || (iOException instanceof ConnectionShutdownException))) {
|
||||
if (this.connection.successCount == 0) {
|
||||
if (this.route != null && iOException != null) {
|
||||
this.routeSelector.connectFailed(this.route, iOException);
|
||||
}
|
||||
this.route = null;
|
||||
}
|
||||
z = true;
|
||||
}
|
||||
z = false;
|
||||
}
|
||||
realConnection = this.connection;
|
||||
deallocate = deallocate(z, false, true);
|
||||
if (this.connection != null || !this.reportedAcquired) {
|
||||
realConnection = null;
|
||||
}
|
||||
}
|
||||
Util.closeQuietly(deallocate);
|
||||
if (realConnection != null) {
|
||||
this.eventListener.connectionReleased(this.call, realConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public void streamFinished(boolean z, HttpCodec httpCodec, long j, IOException iOException) {
|
||||
RealConnection realConnection;
|
||||
Socket deallocate;
|
||||
boolean z2;
|
||||
this.eventListener.responseBodyEnd(this.call, j);
|
||||
synchronized (this.connectionPool) {
|
||||
if (httpCodec != null) {
|
||||
if (httpCodec == this.codec) {
|
||||
if (!z) {
|
||||
this.connection.successCount++;
|
||||
}
|
||||
realConnection = this.connection;
|
||||
deallocate = deallocate(z, false, true);
|
||||
if (this.connection != null) {
|
||||
realConnection = null;
|
||||
}
|
||||
z2 = this.released;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("expected " + this.codec + " but was " + httpCodec);
|
||||
}
|
||||
Util.closeQuietly(deallocate);
|
||||
if (realConnection != null) {
|
||||
this.eventListener.connectionReleased(this.call, realConnection);
|
||||
}
|
||||
if (iOException != null) {
|
||||
this.eventListener.callFailed(this.call, iOException);
|
||||
} else if (z2) {
|
||||
this.eventListener.callEnd(this.call);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
RealConnection connection = connection();
|
||||
return connection != null ? connection.toString() : this.address.toString();
|
||||
}
|
||||
|
||||
private void release(RealConnection realConnection) {
|
||||
int size = realConnection.allocations.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (realConnection.allocations.get(i).get() == this) {
|
||||
realConnection.allocations.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
87
sources/okhttp3/internal/http/BridgeInterceptor.java
Normal file
87
sources/okhttp3/internal/http/BridgeInterceptor.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.Version;
|
||||
import okio.GzipSource;
|
||||
import okio.Okio;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class BridgeInterceptor implements Interceptor {
|
||||
private final CookieJar cookieJar;
|
||||
|
||||
public BridgeInterceptor(CookieJar cookieJar) {
|
||||
this.cookieJar = cookieJar;
|
||||
}
|
||||
|
||||
private String cookieHeader(List<Cookie> list) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i > 0) {
|
||||
sb.append("; ");
|
||||
}
|
||||
Cookie cookie = list.get(i);
|
||||
sb.append(cookie.name());
|
||||
sb.append('=');
|
||||
sb.append(cookie.value());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
Request.Builder newBuilder = request.newBuilder();
|
||||
RequestBody body = request.body();
|
||||
if (body != null) {
|
||||
MediaType contentType = body.contentType();
|
||||
if (contentType != null) {
|
||||
newBuilder.header("Content-Type", contentType.toString());
|
||||
}
|
||||
long contentLength = body.contentLength();
|
||||
if (contentLength != -1) {
|
||||
newBuilder.header("Content-Length", Long.toString(contentLength));
|
||||
newBuilder.removeHeader("Transfer-Encoding");
|
||||
} else {
|
||||
newBuilder.header("Transfer-Encoding", "chunked");
|
||||
newBuilder.removeHeader("Content-Length");
|
||||
}
|
||||
}
|
||||
boolean z = false;
|
||||
if (request.header("Host") == null) {
|
||||
newBuilder.header("Host", Util.hostHeader(request.url(), false));
|
||||
}
|
||||
if (request.header("Connection") == null) {
|
||||
newBuilder.header("Connection", "Keep-Alive");
|
||||
}
|
||||
if (request.header("Accept-Encoding") == null && request.header("Range") == null) {
|
||||
z = true;
|
||||
newBuilder.header("Accept-Encoding", "gzip");
|
||||
}
|
||||
List<Cookie> loadForRequest = this.cookieJar.loadForRequest(request.url());
|
||||
if (!loadForRequest.isEmpty()) {
|
||||
newBuilder.header("Cookie", cookieHeader(loadForRequest));
|
||||
}
|
||||
if (request.header("User-Agent") == null) {
|
||||
newBuilder.header("User-Agent", Version.userAgent());
|
||||
}
|
||||
Response proceed = chain.proceed(newBuilder.build());
|
||||
HttpHeaders.receiveHeaders(this.cookieJar, request.url(), proceed.headers());
|
||||
Response.Builder request2 = proceed.newBuilder().request(request);
|
||||
if (z && "gzip".equalsIgnoreCase(proceed.header("Content-Encoding")) && HttpHeaders.hasBody(proceed)) {
|
||||
GzipSource gzipSource = new GzipSource(proceed.body().source());
|
||||
request2.headers(proceed.headers().newBuilder().removeAll("Content-Encoding").removeAll("Content-Length").build());
|
||||
request2.body(new RealResponseBody(proceed.header("Content-Type"), -1L, Okio.buffer(gzipSource)));
|
||||
}
|
||||
return request2.build();
|
||||
}
|
||||
}
|
||||
89
sources/okhttp3/internal/http/CallServerInterceptor.java
Normal file
89
sources/okhttp3/internal/http/CallServerInterceptor.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.RealConnection;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class CallServerInterceptor implements Interceptor {
|
||||
private final boolean forWebSocket;
|
||||
|
||||
static final class CountingSink extends ForwardingSink {
|
||||
long successfulCount;
|
||||
|
||||
CountingSink(Sink sink) {
|
||||
super(sink);
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
super.write(buffer, j);
|
||||
this.successfulCount += j;
|
||||
}
|
||||
}
|
||||
|
||||
public CallServerInterceptor(boolean z) {
|
||||
this.forWebSocket = z;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
RealInterceptorChain realInterceptorChain = (RealInterceptorChain) chain;
|
||||
HttpCodec httpStream = realInterceptorChain.httpStream();
|
||||
StreamAllocation streamAllocation = realInterceptorChain.streamAllocation();
|
||||
RealConnection realConnection = (RealConnection) realInterceptorChain.connection();
|
||||
Request request = realInterceptorChain.request();
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
realInterceptorChain.eventListener().requestHeadersStart(realInterceptorChain.call());
|
||||
httpStream.writeRequestHeaders(request);
|
||||
realInterceptorChain.eventListener().requestHeadersEnd(realInterceptorChain.call(), request);
|
||||
Response.Builder builder = null;
|
||||
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
|
||||
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
|
||||
httpStream.flushRequest();
|
||||
realInterceptorChain.eventListener().responseHeadersStart(realInterceptorChain.call());
|
||||
builder = httpStream.readResponseHeaders(true);
|
||||
}
|
||||
if (builder == null) {
|
||||
realInterceptorChain.eventListener().requestBodyStart(realInterceptorChain.call());
|
||||
CountingSink countingSink = new CountingSink(httpStream.createRequestBody(request, request.body().contentLength()));
|
||||
BufferedSink buffer = Okio.buffer(countingSink);
|
||||
request.body().writeTo(buffer);
|
||||
buffer.close();
|
||||
realInterceptorChain.eventListener().requestBodyEnd(realInterceptorChain.call(), countingSink.successfulCount);
|
||||
} else if (!realConnection.isMultiplexed()) {
|
||||
streamAllocation.noNewStreams();
|
||||
}
|
||||
}
|
||||
httpStream.finishRequest();
|
||||
if (builder == null) {
|
||||
realInterceptorChain.eventListener().responseHeadersStart(realInterceptorChain.call());
|
||||
builder = httpStream.readResponseHeaders(false);
|
||||
}
|
||||
Response build = builder.request(request).handshake(streamAllocation.connection().handshake()).sentRequestAtMillis(currentTimeMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
|
||||
int code = build.code();
|
||||
if (code == 100) {
|
||||
build = httpStream.readResponseHeaders(false).request(request).handshake(streamAllocation.connection().handshake()).sentRequestAtMillis(currentTimeMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
|
||||
code = build.code();
|
||||
}
|
||||
realInterceptorChain.eventListener().responseHeadersEnd(realInterceptorChain.call(), build);
|
||||
Response build2 = (this.forWebSocket && code == 101) ? build.newBuilder().body(Util.EMPTY_RESPONSE).build() : build.newBuilder().body(httpStream.openResponseBody(build)).build();
|
||||
if ("close".equalsIgnoreCase(build2.request().header("Connection")) || "close".equalsIgnoreCase(build2.header("Connection"))) {
|
||||
streamAllocation.noNewStreams();
|
||||
}
|
||||
if ((code != 204 && code != 205) || build2.body().contentLength() <= 0) {
|
||||
return build2;
|
||||
}
|
||||
throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + build2.body().contentLength());
|
||||
}
|
||||
}
|
||||
26
sources/okhttp3/internal/http/HttpCodec.java
Normal file
26
sources/okhttp3/internal/http/HttpCodec.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface HttpCodec {
|
||||
public static final int DISCARD_STREAM_TIMEOUT_MILLIS = 100;
|
||||
|
||||
void cancel();
|
||||
|
||||
Sink createRequestBody(Request request, long j);
|
||||
|
||||
void finishRequest() throws IOException;
|
||||
|
||||
void flushRequest() throws IOException;
|
||||
|
||||
ResponseBody openResponseBody(Response response) throws IOException;
|
||||
|
||||
Response.Builder readResponseHeaders(boolean z) throws IOException;
|
||||
|
||||
void writeRequestHeaders(Request request) throws IOException;
|
||||
}
|
||||
60
sources/okhttp3/internal/http/HttpDate.java
Normal file
60
sources/okhttp3/internal/http/HttpDate.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParsePosition;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class HttpDate {
|
||||
public static final long MAX_DATE = 253402300799999L;
|
||||
private static final ThreadLocal<DateFormat> STANDARD_DATE_FORMAT = new ThreadLocal<DateFormat>() { // from class: okhttp3.internal.http.HttpDate.1
|
||||
/* JADX INFO: Access modifiers changed from: protected */
|
||||
@Override // java.lang.ThreadLocal
|
||||
public DateFormat initialValue() {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
|
||||
simpleDateFormat.setLenient(false);
|
||||
simpleDateFormat.setTimeZone(Util.UTC);
|
||||
return simpleDateFormat;
|
||||
}
|
||||
};
|
||||
private static final String[] BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = {"EEE, dd MMM yyyy HH:mm:ss zzz", "EEEE, dd-MMM-yy HH:mm:ss zzz", "EEE MMM d HH:mm:ss yyyy", "EEE, dd-MMM-yyyy HH:mm:ss z", "EEE, dd-MMM-yyyy HH-mm-ss z", "EEE, dd MMM yy HH:mm:ss z", "EEE dd-MMM-yyyy HH:mm:ss z", "EEE dd MMM yyyy HH:mm:ss z", "EEE dd-MMM-yyyy HH-mm-ss z", "EEE dd-MMM-yy HH:mm:ss z", "EEE dd MMM yy HH:mm:ss z", "EEE,dd-MMM-yy HH:mm:ss z", "EEE,dd-MMM-yyyy HH:mm:ss z", "EEE, dd-MM-yyyy HH:mm:ss z", "EEE MMM d yyyy HH:mm:ss z"};
|
||||
private static final DateFormat[] BROWSER_COMPATIBLE_DATE_FORMATS = new DateFormat[BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length];
|
||||
|
||||
private HttpDate() {
|
||||
}
|
||||
|
||||
public static String format(Date date) {
|
||||
return STANDARD_DATE_FORMAT.get().format(date);
|
||||
}
|
||||
|
||||
public static Date parse(String str) {
|
||||
if (str.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
Date parse = STANDARD_DATE_FORMAT.get().parse(str, parsePosition);
|
||||
if (parsePosition.getIndex() == str.length()) {
|
||||
return parse;
|
||||
}
|
||||
synchronized (BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS) {
|
||||
int length = BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
DateFormat dateFormat = BROWSER_COMPATIBLE_DATE_FORMATS[i];
|
||||
if (dateFormat == null) {
|
||||
dateFormat = new SimpleDateFormat(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS[i], Locale.US);
|
||||
dateFormat.setTimeZone(Util.UTC);
|
||||
BROWSER_COMPATIBLE_DATE_FORMATS[i] = dateFormat;
|
||||
}
|
||||
parsePosition.setIndex(0);
|
||||
Date parse2 = dateFormat.parse(str, parsePosition);
|
||||
if (parsePosition.getIndex() != 0) {
|
||||
return parse2;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
sources/okhttp3/internal/http/HttpHeaders.java
Normal file
189
sources/okhttp3/internal/http/HttpHeaders.java
Normal file
@@ -0,0 +1,189 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import okhttp3.Challenge;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class HttpHeaders {
|
||||
private static final Pattern PARAMETER = Pattern.compile(" +([^ \"=]*)=(:?\"([^\"]*)\"|([^ \"=]*)) *(:?,|$)");
|
||||
private static final String QUOTED_STRING = "\"([^\"]*)\"";
|
||||
private static final String TOKEN = "([^ \"=]*)";
|
||||
|
||||
private HttpHeaders() {
|
||||
}
|
||||
|
||||
public static long contentLength(Response response) {
|
||||
return contentLength(response.headers());
|
||||
}
|
||||
|
||||
public static boolean hasBody(Response response) {
|
||||
if (response.request().method().equals("HEAD")) {
|
||||
return false;
|
||||
}
|
||||
int code = response.code();
|
||||
return (((code >= 100 && code < 200) || code == 204 || code == 304) && contentLength(response) == -1 && !"chunked".equalsIgnoreCase(response.header("Transfer-Encoding"))) ? false : true;
|
||||
}
|
||||
|
||||
public static boolean hasVaryAll(Response response) {
|
||||
return hasVaryAll(response.headers());
|
||||
}
|
||||
|
||||
public static List<Challenge> parseChallenges(Headers headers, String str) {
|
||||
ArrayList arrayList = new ArrayList();
|
||||
for (String str2 : headers.values(str)) {
|
||||
int indexOf = str2.indexOf(32);
|
||||
if (indexOf != -1) {
|
||||
String substring = str2.substring(0, indexOf);
|
||||
Matcher matcher = PARAMETER.matcher(str2);
|
||||
String str3 = null;
|
||||
String str4 = null;
|
||||
while (matcher.find(indexOf)) {
|
||||
if (str2.regionMatches(true, matcher.start(1), "realm", 0, 5)) {
|
||||
str3 = matcher.group(3);
|
||||
} else if (str2.regionMatches(true, matcher.start(1), "charset", 0, 7)) {
|
||||
str4 = matcher.group(3);
|
||||
}
|
||||
if (str3 != null && str4 != null) {
|
||||
break;
|
||||
}
|
||||
indexOf = matcher.end();
|
||||
}
|
||||
if (str3 != null) {
|
||||
Challenge challenge = new Challenge(substring, str3);
|
||||
if (str4 != null) {
|
||||
if (str4.equalsIgnoreCase("UTF-8")) {
|
||||
challenge = challenge.withCharset(Util.UTF_8);
|
||||
}
|
||||
}
|
||||
arrayList.add(challenge);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
public static int parseSeconds(String str, int i) {
|
||||
try {
|
||||
long parseLong = Long.parseLong(str);
|
||||
if (parseLong > 2147483647L) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
if (parseLong < 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int) parseLong;
|
||||
} catch (NumberFormatException unused) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
public static void receiveHeaders(CookieJar cookieJar, HttpUrl httpUrl, Headers headers) {
|
||||
if (cookieJar == CookieJar.NO_COOKIES) {
|
||||
return;
|
||||
}
|
||||
List<Cookie> parseAll = Cookie.parseAll(httpUrl, headers);
|
||||
if (parseAll.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
cookieJar.saveFromResponse(httpUrl, parseAll);
|
||||
}
|
||||
|
||||
public static int skipUntil(String str, int i, String str2) {
|
||||
while (i < str.length() && str2.indexOf(str.charAt(i)) == -1) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int skipWhitespace(String str, int i) {
|
||||
char charAt;
|
||||
while (i < str.length() && ((charAt = str.charAt(i)) == ' ' || charAt == '\t')) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static long stringToLong(String str) {
|
||||
if (str == null) {
|
||||
return -1L;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(str);
|
||||
} catch (NumberFormatException unused) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> varyFields(Response response) {
|
||||
return varyFields(response.headers());
|
||||
}
|
||||
|
||||
public static Headers varyHeaders(Response response) {
|
||||
return varyHeaders(response.networkResponse().request().headers(), response.headers());
|
||||
}
|
||||
|
||||
public static boolean varyMatches(Response response, Headers headers, Request request) {
|
||||
for (String str : varyFields(response)) {
|
||||
if (!Util.equal(headers.values(str), request.headers(str))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static long contentLength(Headers headers) {
|
||||
return stringToLong(headers.get("Content-Length"));
|
||||
}
|
||||
|
||||
public static boolean hasVaryAll(Headers headers) {
|
||||
return varyFields(headers).contains("*");
|
||||
}
|
||||
|
||||
public static Set<String> varyFields(Headers headers) {
|
||||
Set<String> emptySet = Collections.emptySet();
|
||||
int size = headers.size();
|
||||
Set<String> set = emptySet;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if ("Vary".equalsIgnoreCase(headers.name(i))) {
|
||||
String value = headers.value(i);
|
||||
if (set.isEmpty()) {
|
||||
set = new TreeSet<>((Comparator<? super String>) String.CASE_INSENSITIVE_ORDER);
|
||||
}
|
||||
for (String str : value.split(",")) {
|
||||
set.add(str.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public static Headers varyHeaders(Headers headers, Headers headers2) {
|
||||
Set<String> varyFields = varyFields(headers2);
|
||||
if (varyFields.isEmpty()) {
|
||||
return new Headers.Builder().build();
|
||||
}
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String name = headers.name(i);
|
||||
if (varyFields.contains(name)) {
|
||||
builder.add(name, headers.value(i));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
27
sources/okhttp3/internal/http/HttpMethod.java
Normal file
27
sources/okhttp3/internal/http/HttpMethod.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class HttpMethod {
|
||||
private HttpMethod() {
|
||||
}
|
||||
|
||||
public static boolean invalidatesCache(String str) {
|
||||
return str.equals("POST") || str.equals("PATCH") || str.equals("PUT") || str.equals("DELETE") || str.equals("MOVE");
|
||||
}
|
||||
|
||||
public static boolean permitsRequestBody(String str) {
|
||||
return (str.equals("GET") || str.equals("HEAD")) ? false : true;
|
||||
}
|
||||
|
||||
public static boolean redirectsToGet(String str) {
|
||||
return !str.equals("PROPFIND");
|
||||
}
|
||||
|
||||
public static boolean redirectsWithBody(String str) {
|
||||
return str.equals("PROPFIND");
|
||||
}
|
||||
|
||||
public static boolean requiresRequestBody(String str) {
|
||||
return str.equals("POST") || str.equals("PUT") || str.equals("PATCH") || str.equals("PROPPATCH") || str.equals("REPORT");
|
||||
}
|
||||
}
|
||||
132
sources/okhttp3/internal/http/RealInterceptorChain.java
Normal file
132
sources/okhttp3/internal/http/RealInterceptorChain.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Connection;
|
||||
import okhttp3.EventListener;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.RealConnection;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RealInterceptorChain implements Interceptor.Chain {
|
||||
private final Call call;
|
||||
private int calls;
|
||||
private final int connectTimeout;
|
||||
private final RealConnection connection;
|
||||
private final EventListener eventListener;
|
||||
private final HttpCodec httpCodec;
|
||||
private final int index;
|
||||
private final List<Interceptor> interceptors;
|
||||
private final int readTimeout;
|
||||
private final Request request;
|
||||
private final StreamAllocation streamAllocation;
|
||||
private final int writeTimeout;
|
||||
|
||||
public RealInterceptorChain(List<Interceptor> list, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection realConnection, int i, Request request, Call call, EventListener eventListener, int i2, int i3, int i4) {
|
||||
this.interceptors = list;
|
||||
this.connection = realConnection;
|
||||
this.streamAllocation = streamAllocation;
|
||||
this.httpCodec = httpCodec;
|
||||
this.index = i;
|
||||
this.request = request;
|
||||
this.call = call;
|
||||
this.eventListener = eventListener;
|
||||
this.connectTimeout = i2;
|
||||
this.readTimeout = i3;
|
||||
this.writeTimeout = i4;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Call call() {
|
||||
return this.call;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public int connectTimeoutMillis() {
|
||||
return this.connectTimeout;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Connection connection() {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
public EventListener eventListener() {
|
||||
return this.eventListener;
|
||||
}
|
||||
|
||||
public HttpCodec httpStream() {
|
||||
return this.httpCodec;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Response proceed(Request request) throws IOException {
|
||||
return proceed(request, this.streamAllocation, this.httpCodec, this.connection);
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public int readTimeoutMillis() {
|
||||
return this.readTimeout;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Request request() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
public StreamAllocation streamAllocation() {
|
||||
return this.streamAllocation;
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Interceptor.Chain withConnectTimeout(int i, TimeUnit timeUnit) {
|
||||
return new RealInterceptorChain(this.interceptors, this.streamAllocation, this.httpCodec, this.connection, this.index, this.request, this.call, this.eventListener, Util.checkDuration("timeout", i, timeUnit), this.readTimeout, this.writeTimeout);
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Interceptor.Chain withReadTimeout(int i, TimeUnit timeUnit) {
|
||||
return new RealInterceptorChain(this.interceptors, this.streamAllocation, this.httpCodec, this.connection, this.index, this.request, this.call, this.eventListener, this.connectTimeout, Util.checkDuration("timeout", i, timeUnit), this.writeTimeout);
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public Interceptor.Chain withWriteTimeout(int i, TimeUnit timeUnit) {
|
||||
return new RealInterceptorChain(this.interceptors, this.streamAllocation, this.httpCodec, this.connection, this.index, this.request, this.call, this.eventListener, this.connectTimeout, this.readTimeout, Util.checkDuration("timeout", i, timeUnit));
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor.Chain
|
||||
public int writeTimeoutMillis() {
|
||||
return this.writeTimeout;
|
||||
}
|
||||
|
||||
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection realConnection) throws IOException {
|
||||
if (this.index >= this.interceptors.size()) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
this.calls++;
|
||||
if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
|
||||
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must retain the same host and port");
|
||||
}
|
||||
if (this.httpCodec != null && this.calls > 1) {
|
||||
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must call proceed() exactly once");
|
||||
}
|
||||
RealInterceptorChain realInterceptorChain = new RealInterceptorChain(this.interceptors, streamAllocation, httpCodec, realConnection, this.index + 1, request, this.call, this.eventListener, this.connectTimeout, this.readTimeout, this.writeTimeout);
|
||||
Interceptor interceptor = this.interceptors.get(this.index);
|
||||
Response intercept = interceptor.intercept(realInterceptorChain);
|
||||
if (httpCodec != null && this.index + 1 < this.interceptors.size() && realInterceptorChain.calls != 1) {
|
||||
throw new IllegalStateException("network interceptor " + interceptor + " must call proceed() exactly once");
|
||||
}
|
||||
if (intercept == null) {
|
||||
throw new NullPointerException("interceptor " + interceptor + " returned null");
|
||||
}
|
||||
if (intercept.body() != null) {
|
||||
return intercept;
|
||||
}
|
||||
throw new IllegalStateException("interceptor " + interceptor + " returned a response with no body");
|
||||
}
|
||||
}
|
||||
37
sources/okhttp3/internal/http/RealResponseBody.java
Normal file
37
sources/okhttp3/internal/http/RealResponseBody.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.BufferedSource;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RealResponseBody extends ResponseBody {
|
||||
private final long contentLength;
|
||||
private final String contentTypeString;
|
||||
private final BufferedSource source;
|
||||
|
||||
public RealResponseBody(String str, long j, BufferedSource bufferedSource) {
|
||||
this.contentTypeString = str;
|
||||
this.contentLength = j;
|
||||
this.source = bufferedSource;
|
||||
}
|
||||
|
||||
@Override // okhttp3.ResponseBody
|
||||
public long contentLength() {
|
||||
return this.contentLength;
|
||||
}
|
||||
|
||||
@Override // okhttp3.ResponseBody
|
||||
public MediaType contentType() {
|
||||
String str = this.contentTypeString;
|
||||
if (str != null) {
|
||||
return MediaType.parse(str);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override // okhttp3.ResponseBody
|
||||
public BufferedSource source() {
|
||||
return this.source;
|
||||
}
|
||||
}
|
||||
37
sources/okhttp3/internal/http/RequestLine.java
Normal file
37
sources/okhttp3/internal/http/RequestLine.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.net.Proxy;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RequestLine {
|
||||
private RequestLine() {
|
||||
}
|
||||
|
||||
public static String get(Request request, Proxy.Type type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(request.method());
|
||||
sb.append(' ');
|
||||
if (includeAuthorityInRequestLine(request, type)) {
|
||||
sb.append(request.url());
|
||||
} else {
|
||||
sb.append(requestPath(request.url()));
|
||||
}
|
||||
sb.append(" HTTP/1.1");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static boolean includeAuthorityInRequestLine(Request request, Proxy.Type type) {
|
||||
return !request.isHttps() && type == Proxy.Type.HTTP;
|
||||
}
|
||||
|
||||
public static String requestPath(HttpUrl httpUrl) {
|
||||
String encodedPath = httpUrl.encodedPath();
|
||||
String encodedQuery = httpUrl.encodedQuery();
|
||||
if (encodedQuery == null) {
|
||||
return encodedPath;
|
||||
}
|
||||
return encodedPath + '?' + encodedQuery;
|
||||
}
|
||||
}
|
||||
256
sources/okhttp3/internal/http/RetryAndFollowUpInterceptor.java
Normal file
256
sources/okhttp3/internal/http/RetryAndFollowUpInterceptor.java
Normal file
@@ -0,0 +1,256 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import com.ubt.jimu.diy.model.DiyPreviewStep;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.HttpRetryException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.cert.CertificateException;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import okhttp3.Address;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.CertificatePinner;
|
||||
import okhttp3.EventListener;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.Route;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.RouteException;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
import okhttp3.internal.http2.ConnectionShutdownException;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RetryAndFollowUpInterceptor implements Interceptor {
|
||||
private static final int MAX_FOLLOW_UPS = 20;
|
||||
private Object callStackTrace;
|
||||
private volatile boolean canceled;
|
||||
private final OkHttpClient client;
|
||||
private final boolean forWebSocket;
|
||||
private volatile StreamAllocation streamAllocation;
|
||||
|
||||
public RetryAndFollowUpInterceptor(OkHttpClient okHttpClient, boolean z) {
|
||||
this.client = okHttpClient;
|
||||
this.forWebSocket = z;
|
||||
}
|
||||
|
||||
private Address createAddress(HttpUrl httpUrl) {
|
||||
SSLSocketFactory sSLSocketFactory;
|
||||
HostnameVerifier hostnameVerifier;
|
||||
CertificatePinner certificatePinner;
|
||||
if (httpUrl.isHttps()) {
|
||||
SSLSocketFactory sslSocketFactory = this.client.sslSocketFactory();
|
||||
hostnameVerifier = this.client.hostnameVerifier();
|
||||
sSLSocketFactory = sslSocketFactory;
|
||||
certificatePinner = this.client.certificatePinner();
|
||||
} else {
|
||||
sSLSocketFactory = null;
|
||||
hostnameVerifier = null;
|
||||
certificatePinner = null;
|
||||
}
|
||||
return new Address(httpUrl.host(), httpUrl.port(), this.client.dns(), this.client.socketFactory(), sSLSocketFactory, hostnameVerifier, certificatePinner, this.client.proxyAuthenticator(), this.client.proxy(), this.client.protocols(), this.client.connectionSpecs(), this.client.proxySelector());
|
||||
}
|
||||
|
||||
private Request followUpRequest(Response response, Route route) throws IOException {
|
||||
String header;
|
||||
HttpUrl resolve;
|
||||
if (response == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int code = response.code();
|
||||
String method = response.request().method();
|
||||
if (code == 307 || code == 308) {
|
||||
if (!method.equals("GET") && !method.equals("HEAD")) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (code == 401) {
|
||||
return this.client.authenticator().authenticate(route, response);
|
||||
}
|
||||
if (code == 503) {
|
||||
if ((response.priorResponse() == null || response.priorResponse().code() != 503) && retryAfter(response, Integer.MAX_VALUE) == 0) {
|
||||
return response.request();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (code == 407) {
|
||||
if ((route != null ? route.proxy() : this.client.proxy()).type() == Proxy.Type.HTTP) {
|
||||
return this.client.proxyAuthenticator().authenticate(route, response);
|
||||
}
|
||||
throw new ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy");
|
||||
}
|
||||
if (code == 408) {
|
||||
if (!this.client.retryOnConnectionFailure() || (response.request().body() instanceof UnrepeatableRequestBody)) {
|
||||
return null;
|
||||
}
|
||||
if ((response.priorResponse() == null || response.priorResponse().code() != 408) && retryAfter(response, 0) <= 0) {
|
||||
return response.request();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
switch (code) {
|
||||
case 300:
|
||||
case DiyPreviewStep.TYPE_PROGRAM /* 301 */:
|
||||
case 302:
|
||||
case 303:
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!this.client.followRedirects() || (header = response.header("Location")) == null || (resolve = response.request().url().resolve(header)) == null) {
|
||||
return null;
|
||||
}
|
||||
if (!resolve.scheme().equals(response.request().url().scheme()) && !this.client.followSslRedirects()) {
|
||||
return null;
|
||||
}
|
||||
Request.Builder newBuilder = response.request().newBuilder();
|
||||
if (HttpMethod.permitsRequestBody(method)) {
|
||||
boolean redirectsWithBody = HttpMethod.redirectsWithBody(method);
|
||||
if (HttpMethod.redirectsToGet(method)) {
|
||||
newBuilder.method("GET", null);
|
||||
} else {
|
||||
newBuilder.method(method, redirectsWithBody ? response.request().body() : null);
|
||||
}
|
||||
if (!redirectsWithBody) {
|
||||
newBuilder.removeHeader("Transfer-Encoding");
|
||||
newBuilder.removeHeader("Content-Length");
|
||||
newBuilder.removeHeader("Content-Type");
|
||||
}
|
||||
}
|
||||
if (!sameConnection(response, resolve)) {
|
||||
newBuilder.removeHeader("Authorization");
|
||||
}
|
||||
return newBuilder.url(resolve).build();
|
||||
}
|
||||
|
||||
private boolean isRecoverable(IOException iOException, boolean z) {
|
||||
if (iOException instanceof ProtocolException) {
|
||||
return false;
|
||||
}
|
||||
return iOException instanceof InterruptedIOException ? (iOException instanceof SocketTimeoutException) && !z : (((iOException instanceof SSLHandshakeException) && (iOException.getCause() instanceof CertificateException)) || (iOException instanceof SSLPeerUnverifiedException)) ? false : true;
|
||||
}
|
||||
|
||||
private boolean recover(IOException iOException, StreamAllocation streamAllocation, boolean z, Request request) {
|
||||
streamAllocation.streamFailed(iOException);
|
||||
if (this.client.retryOnConnectionFailure()) {
|
||||
return !(z && (request.body() instanceof UnrepeatableRequestBody)) && isRecoverable(iOException, z) && streamAllocation.hasMoreRoutes();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int retryAfter(Response response, int i) {
|
||||
String header = response.header("Retry-After");
|
||||
if (header == null) {
|
||||
return i;
|
||||
}
|
||||
if (header.matches("\\d+")) {
|
||||
return Integer.valueOf(header).intValue();
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
private boolean sameConnection(Response response, HttpUrl httpUrl) {
|
||||
HttpUrl url = response.request().url();
|
||||
return url.host().equals(httpUrl.host()) && url.port() == httpUrl.port() && url.scheme().equals(httpUrl.scheme());
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.canceled = true;
|
||||
StreamAllocation streamAllocation = this.streamAllocation;
|
||||
if (streamAllocation != null) {
|
||||
streamAllocation.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
Response proceed;
|
||||
Request followUpRequest;
|
||||
Request request = chain.request();
|
||||
RealInterceptorChain realInterceptorChain = (RealInterceptorChain) chain;
|
||||
Call call = realInterceptorChain.call();
|
||||
EventListener eventListener = realInterceptorChain.eventListener();
|
||||
StreamAllocation streamAllocation = new StreamAllocation(this.client.connectionPool(), createAddress(request.url()), call, eventListener, this.callStackTrace);
|
||||
this.streamAllocation = streamAllocation;
|
||||
Response response = null;
|
||||
int i = 0;
|
||||
while (!this.canceled) {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
proceed = realInterceptorChain.proceed(request, streamAllocation, null, null);
|
||||
if (response != null) {
|
||||
proceed = proceed.newBuilder().priorResponse(response.newBuilder().body(null).build()).build();
|
||||
}
|
||||
try {
|
||||
followUpRequest = followUpRequest(proceed, streamAllocation.route());
|
||||
} catch (IOException e) {
|
||||
streamAllocation.release();
|
||||
throw e;
|
||||
}
|
||||
} catch (RouteException e2) {
|
||||
if (!recover(e2.getLastConnectException(), streamAllocation, false, request)) {
|
||||
throw e2.getFirstConnectException();
|
||||
}
|
||||
}
|
||||
} catch (IOException e3) {
|
||||
if (!recover(e3, streamAllocation, !(e3 instanceof ConnectionShutdownException), request)) {
|
||||
throw e3;
|
||||
}
|
||||
}
|
||||
if (followUpRequest == null) {
|
||||
if (!this.forWebSocket) {
|
||||
streamAllocation.release();
|
||||
}
|
||||
return proceed;
|
||||
}
|
||||
Util.closeQuietly(proceed.body());
|
||||
int i2 = i + 1;
|
||||
if (i2 > 20) {
|
||||
streamAllocation.release();
|
||||
throw new ProtocolException("Too many follow-up requests: " + i2);
|
||||
}
|
||||
if (followUpRequest.body() instanceof UnrepeatableRequestBody) {
|
||||
streamAllocation.release();
|
||||
throw new HttpRetryException("Cannot retry streamed HTTP body", proceed.code());
|
||||
}
|
||||
if (!sameConnection(proceed, followUpRequest.url())) {
|
||||
streamAllocation.release();
|
||||
streamAllocation = new StreamAllocation(this.client.connectionPool(), createAddress(followUpRequest.url()), call, eventListener, this.callStackTrace);
|
||||
this.streamAllocation = streamAllocation;
|
||||
} else if (streamAllocation.codec() != null) {
|
||||
throw new IllegalStateException("Closing the body of " + proceed + " didn't close its backing stream. Bad interceptor?");
|
||||
}
|
||||
response = proceed;
|
||||
request = followUpRequest;
|
||||
i = i2;
|
||||
} catch (Throwable th) {
|
||||
streamAllocation.streamFailed(null);
|
||||
streamAllocation.release();
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
streamAllocation.release();
|
||||
throw new IOException("Canceled");
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return this.canceled;
|
||||
}
|
||||
|
||||
public void setCallStackTrace(Object obj) {
|
||||
this.callStackTrace = obj;
|
||||
}
|
||||
|
||||
public StreamAllocation streamAllocation() {
|
||||
return this.streamAllocation;
|
||||
}
|
||||
}
|
||||
82
sources/okhttp3/internal/http/StatusLine.java
Normal file
82
sources/okhttp3/internal/http/StatusLine.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Response;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class StatusLine {
|
||||
public static final int HTTP_CONTINUE = 100;
|
||||
public static final int HTTP_PERM_REDIRECT = 308;
|
||||
public static final int HTTP_TEMP_REDIRECT = 307;
|
||||
public final int code;
|
||||
public final String message;
|
||||
public final Protocol protocol;
|
||||
|
||||
public StatusLine(Protocol protocol, int i, String str) {
|
||||
this.protocol = protocol;
|
||||
this.code = i;
|
||||
this.message = str;
|
||||
}
|
||||
|
||||
public static StatusLine get(Response response) {
|
||||
return new StatusLine(response.protocol(), response.code(), response.message());
|
||||
}
|
||||
|
||||
public static StatusLine parse(String str) throws IOException {
|
||||
Protocol protocol;
|
||||
String str2;
|
||||
int i = 9;
|
||||
if (str.startsWith("HTTP/1.")) {
|
||||
if (str.length() < 9 || str.charAt(8) != ' ') {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
int charAt = str.charAt(7) - '0';
|
||||
if (charAt == 0) {
|
||||
protocol = Protocol.HTTP_1_0;
|
||||
} else {
|
||||
if (charAt != 1) {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
protocol = Protocol.HTTP_1_1;
|
||||
}
|
||||
} else {
|
||||
if (!str.startsWith("ICY ")) {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
protocol = Protocol.HTTP_1_0;
|
||||
i = 4;
|
||||
}
|
||||
int i2 = i + 3;
|
||||
if (str.length() < i2) {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
try {
|
||||
int parseInt = Integer.parseInt(str.substring(i, i2));
|
||||
if (str.length() <= i2) {
|
||||
str2 = "";
|
||||
} else {
|
||||
if (str.charAt(i2) != ' ') {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
str2 = str.substring(i + 4);
|
||||
}
|
||||
return new StatusLine(protocol, parseInt, str2);
|
||||
} catch (NumberFormatException unused) {
|
||||
throw new ProtocolException("Unexpected status line: " + str);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1");
|
||||
sb.append(' ');
|
||||
sb.append(this.code);
|
||||
if (this.message != null) {
|
||||
sb.append(' ');
|
||||
sb.append(this.message);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package okhttp3.internal.http;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface UnrepeatableRequestBody {
|
||||
}
|
||||
521
sources/okhttp3/internal/http1/Http1Codec.java
Normal file
521
sources/okhttp3/internal/http1/Http1Codec.java
Normal file
@@ -0,0 +1,521 @@
|
||||
package okhttp3.internal.http1;
|
||||
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.RealConnection;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
import okhttp3.internal.http.HttpCodec;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.http.RealResponseBody;
|
||||
import okhttp3.internal.http.RequestLine;
|
||||
import okhttp3.internal.http.StatusLine;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.ForwardingTimeout;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Http1Codec implements HttpCodec {
|
||||
private static final int HEADER_LIMIT = 262144;
|
||||
private static final int STATE_CLOSED = 6;
|
||||
private static final int STATE_IDLE = 0;
|
||||
private static final int STATE_OPEN_REQUEST_BODY = 1;
|
||||
private static final int STATE_OPEN_RESPONSE_BODY = 4;
|
||||
private static final int STATE_READING_RESPONSE_BODY = 5;
|
||||
private static final int STATE_READ_RESPONSE_HEADERS = 3;
|
||||
private static final int STATE_WRITING_REQUEST_BODY = 2;
|
||||
final OkHttpClient client;
|
||||
final BufferedSink sink;
|
||||
final BufferedSource source;
|
||||
final StreamAllocation streamAllocation;
|
||||
int state = 0;
|
||||
private long headerLimit = PlaybackStateCompat.ACTION_SET_REPEAT_MODE;
|
||||
|
||||
private abstract class AbstractSource implements Source {
|
||||
protected long bytesRead;
|
||||
protected boolean closed;
|
||||
protected final ForwardingTimeout timeout;
|
||||
|
||||
private AbstractSource() {
|
||||
this.timeout = new ForwardingTimeout(Http1Codec.this.source.timeout());
|
||||
this.bytesRead = 0L;
|
||||
}
|
||||
|
||||
protected final void endOfInput(boolean z, IOException iOException) throws IOException {
|
||||
Http1Codec http1Codec = Http1Codec.this;
|
||||
int i = http1Codec.state;
|
||||
if (i == 6) {
|
||||
return;
|
||||
}
|
||||
if (i != 5) {
|
||||
throw new IllegalStateException("state: " + Http1Codec.this.state);
|
||||
}
|
||||
http1Codec.detachTimeout(this.timeout);
|
||||
Http1Codec http1Codec2 = Http1Codec.this;
|
||||
http1Codec2.state = 6;
|
||||
StreamAllocation streamAllocation = http1Codec2.streamAllocation;
|
||||
if (streamAllocation != null) {
|
||||
streamAllocation.streamFinished(!z, http1Codec2, this.bytesRead, iOException);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
try {
|
||||
long read = Http1Codec.this.source.read(buffer, j);
|
||||
if (read > 0) {
|
||||
this.bytesRead += read;
|
||||
}
|
||||
return read;
|
||||
} catch (IOException e) {
|
||||
endOfInput(false, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
}
|
||||
|
||||
private final class ChunkedSink implements Sink {
|
||||
private boolean closed;
|
||||
private final ForwardingTimeout timeout;
|
||||
|
||||
ChunkedSink() {
|
||||
this.timeout = new ForwardingTimeout(Http1Codec.this.sink.timeout());
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public synchronized void close() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
Http1Codec.this.sink.writeUtf8("0\r\n\r\n");
|
||||
Http1Codec.this.detachTimeout(this.timeout);
|
||||
Http1Codec.this.state = 3;
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Flushable
|
||||
public synchronized void flush() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
Http1Codec.this.sink.flush();
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public Timeout timeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("closed");
|
||||
}
|
||||
if (j == 0) {
|
||||
return;
|
||||
}
|
||||
Http1Codec.this.sink.writeHexadecimalUnsignedLong(j);
|
||||
Http1Codec.this.sink.writeUtf8("\r\n");
|
||||
Http1Codec.this.sink.write(buffer, j);
|
||||
Http1Codec.this.sink.writeUtf8("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
private class ChunkedSource extends AbstractSource {
|
||||
private static final long NO_CHUNK_YET = -1;
|
||||
private long bytesRemainingInChunk;
|
||||
private boolean hasMoreChunks;
|
||||
private final HttpUrl url;
|
||||
|
||||
ChunkedSource(HttpUrl httpUrl) {
|
||||
super();
|
||||
this.bytesRemainingInChunk = -1L;
|
||||
this.hasMoreChunks = true;
|
||||
this.url = httpUrl;
|
||||
}
|
||||
|
||||
private void readChunkSize() throws IOException {
|
||||
if (this.bytesRemainingInChunk != -1) {
|
||||
Http1Codec.this.source.readUtf8LineStrict();
|
||||
}
|
||||
try {
|
||||
this.bytesRemainingInChunk = Http1Codec.this.source.readHexadecimalUnsignedLong();
|
||||
String trim = Http1Codec.this.source.readUtf8LineStrict().trim();
|
||||
if (this.bytesRemainingInChunk < 0 || !(trim.isEmpty() || trim.startsWith(";"))) {
|
||||
throw new ProtocolException("expected chunk size and optional extensions but was \"" + this.bytesRemainingInChunk + trim + "\"");
|
||||
}
|
||||
if (this.bytesRemainingInChunk == 0) {
|
||||
this.hasMoreChunks = false;
|
||||
HttpHeaders.receiveHeaders(Http1Codec.this.client.cookieJar(), this.url, Http1Codec.this.readHeaders());
|
||||
endOfInput(true, null);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ProtocolException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
if (this.hasMoreChunks && !Util.discard(this, 100, TimeUnit.MILLISECONDS)) {
|
||||
endOfInput(false, null);
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http1.Http1Codec.AbstractSource, okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
if (j < 0) {
|
||||
throw new IllegalArgumentException("byteCount < 0: " + j);
|
||||
}
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("closed");
|
||||
}
|
||||
if (!this.hasMoreChunks) {
|
||||
return -1L;
|
||||
}
|
||||
long j2 = this.bytesRemainingInChunk;
|
||||
if (j2 == 0 || j2 == -1) {
|
||||
readChunkSize();
|
||||
if (!this.hasMoreChunks) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
long read = super.read(buffer, Math.min(j, this.bytesRemainingInChunk));
|
||||
if (read != -1) {
|
||||
this.bytesRemainingInChunk -= read;
|
||||
return read;
|
||||
}
|
||||
ProtocolException protocolException = new ProtocolException("unexpected end of stream");
|
||||
endOfInput(false, protocolException);
|
||||
throw protocolException;
|
||||
}
|
||||
}
|
||||
|
||||
private final class FixedLengthSink implements Sink {
|
||||
private long bytesRemaining;
|
||||
private boolean closed;
|
||||
private final ForwardingTimeout timeout;
|
||||
|
||||
FixedLengthSink(long j) {
|
||||
this.timeout = new ForwardingTimeout(Http1Codec.this.sink.timeout());
|
||||
this.bytesRemaining = j;
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
if (this.bytesRemaining > 0) {
|
||||
throw new ProtocolException("unexpected end of stream");
|
||||
}
|
||||
Http1Codec.this.detachTimeout(this.timeout);
|
||||
Http1Codec.this.state = 3;
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Flushable
|
||||
public void flush() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
Http1Codec.this.sink.flush();
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public Timeout timeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("closed");
|
||||
}
|
||||
Util.checkOffsetAndCount(buffer.size(), 0L, j);
|
||||
if (j <= this.bytesRemaining) {
|
||||
Http1Codec.this.sink.write(buffer, j);
|
||||
this.bytesRemaining -= j;
|
||||
return;
|
||||
}
|
||||
throw new ProtocolException("expected " + this.bytesRemaining + " bytes but received " + j);
|
||||
}
|
||||
}
|
||||
|
||||
private class FixedLengthSource extends AbstractSource {
|
||||
private long bytesRemaining;
|
||||
|
||||
FixedLengthSource(long j) throws IOException {
|
||||
super();
|
||||
this.bytesRemaining = j;
|
||||
if (this.bytesRemaining == 0) {
|
||||
endOfInput(true, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
if (this.bytesRemaining != 0 && !Util.discard(this, 100, TimeUnit.MILLISECONDS)) {
|
||||
endOfInput(false, null);
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http1.Http1Codec.AbstractSource, okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
if (j < 0) {
|
||||
throw new IllegalArgumentException("byteCount < 0: " + j);
|
||||
}
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("closed");
|
||||
}
|
||||
long j2 = this.bytesRemaining;
|
||||
if (j2 == 0) {
|
||||
return -1L;
|
||||
}
|
||||
long read = super.read(buffer, Math.min(j2, j));
|
||||
if (read == -1) {
|
||||
ProtocolException protocolException = new ProtocolException("unexpected end of stream");
|
||||
endOfInput(false, protocolException);
|
||||
throw protocolException;
|
||||
}
|
||||
this.bytesRemaining -= read;
|
||||
if (this.bytesRemaining == 0) {
|
||||
endOfInput(true, null);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
private class UnknownLengthSource extends AbstractSource {
|
||||
private boolean inputExhausted;
|
||||
|
||||
UnknownLengthSource() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
if (!this.inputExhausted) {
|
||||
endOfInput(false, null);
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http1.Http1Codec.AbstractSource, okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
if (j < 0) {
|
||||
throw new IllegalArgumentException("byteCount < 0: " + j);
|
||||
}
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("closed");
|
||||
}
|
||||
if (this.inputExhausted) {
|
||||
return -1L;
|
||||
}
|
||||
long read = super.read(buffer, j);
|
||||
if (read != -1) {
|
||||
return read;
|
||||
}
|
||||
this.inputExhausted = true;
|
||||
endOfInput(true, null);
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
|
||||
public Http1Codec(OkHttpClient okHttpClient, StreamAllocation streamAllocation, BufferedSource bufferedSource, BufferedSink bufferedSink) {
|
||||
this.client = okHttpClient;
|
||||
this.streamAllocation = streamAllocation;
|
||||
this.source = bufferedSource;
|
||||
this.sink = bufferedSink;
|
||||
}
|
||||
|
||||
private String readHeaderLine() throws IOException {
|
||||
String readUtf8LineStrict = this.source.readUtf8LineStrict(this.headerLimit);
|
||||
this.headerLimit -= readUtf8LineStrict.length();
|
||||
return readUtf8LineStrict;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void cancel() {
|
||||
RealConnection connection = this.streamAllocation.connection();
|
||||
if (connection != null) {
|
||||
connection.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public Sink createRequestBody(Request request, long j) {
|
||||
if ("chunked".equalsIgnoreCase(request.header("Transfer-Encoding"))) {
|
||||
return newChunkedSink();
|
||||
}
|
||||
if (j != -1) {
|
||||
return newFixedLengthSink(j);
|
||||
}
|
||||
throw new IllegalStateException("Cannot stream a request body without chunked encoding or a known content length!");
|
||||
}
|
||||
|
||||
void detachTimeout(ForwardingTimeout forwardingTimeout) {
|
||||
Timeout delegate = forwardingTimeout.delegate();
|
||||
forwardingTimeout.setDelegate(Timeout.NONE);
|
||||
delegate.clearDeadline();
|
||||
delegate.clearTimeout();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void finishRequest() throws IOException {
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void flushRequest() throws IOException {
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.state == 6;
|
||||
}
|
||||
|
||||
public Sink newChunkedSink() {
|
||||
if (this.state == 1) {
|
||||
this.state = 2;
|
||||
return new ChunkedSink();
|
||||
}
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
|
||||
public Source newChunkedSource(HttpUrl httpUrl) throws IOException {
|
||||
if (this.state == 4) {
|
||||
this.state = 5;
|
||||
return new ChunkedSource(httpUrl);
|
||||
}
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
|
||||
public Sink newFixedLengthSink(long j) {
|
||||
if (this.state == 1) {
|
||||
this.state = 2;
|
||||
return new FixedLengthSink(j);
|
||||
}
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
|
||||
public Source newFixedLengthSource(long j) throws IOException {
|
||||
if (this.state == 4) {
|
||||
this.state = 5;
|
||||
return new FixedLengthSource(j);
|
||||
}
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
|
||||
public Source newUnknownLengthSource() throws IOException {
|
||||
if (this.state != 4) {
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
StreamAllocation streamAllocation = this.streamAllocation;
|
||||
if (streamAllocation == null) {
|
||||
throw new IllegalStateException("streamAllocation == null");
|
||||
}
|
||||
this.state = 5;
|
||||
streamAllocation.noNewStreams();
|
||||
return new UnknownLengthSource();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public ResponseBody openResponseBody(Response response) throws IOException {
|
||||
StreamAllocation streamAllocation = this.streamAllocation;
|
||||
streamAllocation.eventListener.responseBodyStart(streamAllocation.call);
|
||||
String header = response.header("Content-Type");
|
||||
if (!HttpHeaders.hasBody(response)) {
|
||||
return new RealResponseBody(header, 0L, Okio.buffer(newFixedLengthSource(0L)));
|
||||
}
|
||||
if ("chunked".equalsIgnoreCase(response.header("Transfer-Encoding"))) {
|
||||
return new RealResponseBody(header, -1L, Okio.buffer(newChunkedSource(response.request().url())));
|
||||
}
|
||||
long contentLength = HttpHeaders.contentLength(response);
|
||||
return contentLength != -1 ? new RealResponseBody(header, contentLength, Okio.buffer(newFixedLengthSource(contentLength))) : new RealResponseBody(header, -1L, Okio.buffer(newUnknownLengthSource()));
|
||||
}
|
||||
|
||||
public Headers readHeaders() throws IOException {
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
while (true) {
|
||||
String readHeaderLine = readHeaderLine();
|
||||
if (readHeaderLine.length() == 0) {
|
||||
return builder.build();
|
||||
}
|
||||
Internal.instance.addLenient(builder, readHeaderLine);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public Response.Builder readResponseHeaders(boolean z) throws IOException {
|
||||
int i = this.state;
|
||||
if (i != 1 && i != 3) {
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
try {
|
||||
StatusLine parse = StatusLine.parse(readHeaderLine());
|
||||
Response.Builder headers = new Response.Builder().protocol(parse.protocol).code(parse.code).message(parse.message).headers(readHeaders());
|
||||
if (z && parse.code == 100) {
|
||||
return null;
|
||||
}
|
||||
if (parse.code == 100) {
|
||||
this.state = 3;
|
||||
return headers;
|
||||
}
|
||||
this.state = 4;
|
||||
return headers;
|
||||
} catch (EOFException e) {
|
||||
IOException iOException = new IOException("unexpected end of stream on " + this.streamAllocation);
|
||||
iOException.initCause(e);
|
||||
throw iOException;
|
||||
}
|
||||
}
|
||||
|
||||
public void writeRequest(Headers headers, String str) throws IOException {
|
||||
if (this.state != 0) {
|
||||
throw new IllegalStateException("state: " + this.state);
|
||||
}
|
||||
this.sink.writeUtf8(str).writeUtf8("\r\n");
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
this.sink.writeUtf8(headers.name(i)).writeUtf8(": ").writeUtf8(headers.value(i)).writeUtf8("\r\n");
|
||||
}
|
||||
this.sink.writeUtf8("\r\n");
|
||||
this.state = 1;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void writeRequestHeaders(Request request) throws IOException {
|
||||
writeRequest(request.headers(), RequestLine.get(request, this.streamAllocation.connection().route().proxy().type()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class ConnectionShutdownException extends IOException {
|
||||
}
|
||||
31
sources/okhttp3/internal/http2/ErrorCode.java
Normal file
31
sources/okhttp3/internal/http2/ErrorCode.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public enum ErrorCode {
|
||||
NO_ERROR(0),
|
||||
PROTOCOL_ERROR(1),
|
||||
INTERNAL_ERROR(2),
|
||||
FLOW_CONTROL_ERROR(3),
|
||||
REFUSED_STREAM(7),
|
||||
CANCEL(8),
|
||||
COMPRESSION_ERROR(9),
|
||||
CONNECT_ERROR(10),
|
||||
ENHANCE_YOUR_CALM(11),
|
||||
INADEQUATE_SECURITY(12),
|
||||
HTTP_1_1_REQUIRED(13);
|
||||
|
||||
public final int httpCode;
|
||||
|
||||
ErrorCode(int i) {
|
||||
this.httpCode = i;
|
||||
}
|
||||
|
||||
public static ErrorCode fromHttp2(int i) {
|
||||
for (ErrorCode errorCode : values()) {
|
||||
if (errorCode.httpCode == i) {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
47
sources/okhttp3/internal/http2/Header.java
Normal file
47
sources/okhttp3/internal/http2/Header.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import okhttp3.internal.Util;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Header {
|
||||
final int hpackSize;
|
||||
public final ByteString name;
|
||||
public final ByteString value;
|
||||
public static final ByteString PSEUDO_PREFIX = ByteString.encodeUtf8(":");
|
||||
public static final ByteString RESPONSE_STATUS = ByteString.encodeUtf8(":status");
|
||||
public static final ByteString TARGET_METHOD = ByteString.encodeUtf8(":method");
|
||||
public static final ByteString TARGET_PATH = ByteString.encodeUtf8(":path");
|
||||
public static final ByteString TARGET_SCHEME = ByteString.encodeUtf8(":scheme");
|
||||
public static final ByteString TARGET_AUTHORITY = ByteString.encodeUtf8(":authority");
|
||||
|
||||
public Header(String str, String str2) {
|
||||
this(ByteString.encodeUtf8(str), ByteString.encodeUtf8(str2));
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Header)) {
|
||||
return false;
|
||||
}
|
||||
Header header = (Header) obj;
|
||||
return this.name.equals(header.name) && this.value.equals(header.value);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ((527 + this.name.hashCode()) * 31) + this.value.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Util.format("%s: %s", this.name.utf8(), this.value.utf8());
|
||||
}
|
||||
|
||||
public Header(ByteString byteString, String str) {
|
||||
this(byteString, ByteString.encodeUtf8(str));
|
||||
}
|
||||
|
||||
public Header(ByteString byteString, ByteString byteString2) {
|
||||
this.name = byteString;
|
||||
this.value = byteString2;
|
||||
this.hpackSize = byteString.size() + 32 + byteString2.size();
|
||||
}
|
||||
}
|
||||
487
sources/okhttp3/internal/http2/Hpack.java
Normal file
487
sources/okhttp3/internal/http2/Hpack.java
Normal file
@@ -0,0 +1,487 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import com.liulishuo.filedownloader.model.FileDownloadModel;
|
||||
import com.ubt.jimu.base.entities.Constant;
|
||||
import com.ubt.jimu.base.http.ApiConstants;
|
||||
import com.ubt.jimu.unity.bluetooth.MyUnityListener;
|
||||
import com.ubtrobot.jimu.robotapi.PeripheralType;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class Hpack {
|
||||
private static final int PREFIX_4_BITS = 15;
|
||||
private static final int PREFIX_5_BITS = 31;
|
||||
private static final int PREFIX_6_BITS = 63;
|
||||
private static final int PREFIX_7_BITS = 127;
|
||||
static final Header[] STATIC_HEADER_TABLE = {new Header(Header.TARGET_AUTHORITY, ""), new Header(Header.TARGET_METHOD, "GET"), new Header(Header.TARGET_METHOD, "POST"), new Header(Header.TARGET_PATH, "/"), new Header(Header.TARGET_PATH, "/index.html"), new Header(Header.TARGET_SCHEME, "http"), new Header(Header.TARGET_SCHEME, "https"), new Header(Header.RESPONSE_STATUS, "200"), new Header(Header.RESPONSE_STATUS, "204"), new Header(Header.RESPONSE_STATUS, "206"), new Header(Header.RESPONSE_STATUS, "304"), new Header(Header.RESPONSE_STATUS, "400"), new Header(Header.RESPONSE_STATUS, "404"), new Header(Header.RESPONSE_STATUS, "500"), new Header("accept-charset", ""), new Header("accept-encoding", "gzip, deflate"), new Header("accept-language", ""), new Header("accept-ranges", ""), new Header("accept", ""), new Header("access-control-allow-origin", ""), new Header("age", ""), new Header("allow", ""), new Header(ApiConstants.AUTHORIZATION, ""), new Header("cache-control", ""), new Header("content-disposition", ""), new Header("content-encoding", ""), new Header("content-language", ""), new Header("content-length", ""), new Header("content-location", ""), new Header("content-range", ""), new Header("content-type", ""), new Header("cookie", ""), new Header("date", ""), new Header(FileDownloadModel.ETAG, ""), new Header("expect", ""), new Header("expires", ""), new Header(MyUnityListener.CALLER, ""), new Header("host", ""), new Header("if-match", ""), new Header("if-modified-since", ""), new Header("if-none-match", ""), new Header("if-range", ""), new Header("if-unmodified-since", ""), new Header("last-modified", ""), new Header(Constant.Community.SOURCE_LINK_TYPE, ""), new Header("location", ""), new Header("max-forwards", ""), new Header("proxy-authenticate", ""), new Header("proxy-authorization", ""), new Header("range", ""), new Header("referer", ""), new Header("refresh", ""), new Header("retry-after", ""), new Header("server", ""), new Header("set-cookie", ""), new Header("strict-transport-security", ""), new Header("transfer-encoding", ""), new Header("user-agent", ""), new Header("vary", ""), new Header("via", ""), new Header("www-authenticate", "")};
|
||||
static final Map<ByteString, Integer> NAME_TO_FIRST_INDEX = nameToFirstIndex();
|
||||
|
||||
static final class Reader {
|
||||
Header[] dynamicTable;
|
||||
int dynamicTableByteCount;
|
||||
int headerCount;
|
||||
private final List<Header> headerList;
|
||||
private final int headerTableSizeSetting;
|
||||
private int maxDynamicTableByteCount;
|
||||
int nextHeaderIndex;
|
||||
private final BufferedSource source;
|
||||
|
||||
Reader(int i, Source source) {
|
||||
this(i, i, source);
|
||||
}
|
||||
|
||||
private void adjustDynamicTableByteCount() {
|
||||
int i = this.maxDynamicTableByteCount;
|
||||
int i2 = this.dynamicTableByteCount;
|
||||
if (i < i2) {
|
||||
if (i == 0) {
|
||||
clearDynamicTable();
|
||||
} else {
|
||||
evictToRecoverBytes(i2 - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearDynamicTable() {
|
||||
Arrays.fill(this.dynamicTable, (Object) null);
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.headerCount = 0;
|
||||
this.dynamicTableByteCount = 0;
|
||||
}
|
||||
|
||||
private int dynamicTableIndex(int i) {
|
||||
return this.nextHeaderIndex + 1 + i;
|
||||
}
|
||||
|
||||
private int evictToRecoverBytes(int i) {
|
||||
int i2 = 0;
|
||||
if (i > 0) {
|
||||
int length = this.dynamicTable.length;
|
||||
while (true) {
|
||||
length--;
|
||||
if (length < this.nextHeaderIndex || i <= 0) {
|
||||
break;
|
||||
}
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
i -= headerArr[length].hpackSize;
|
||||
this.dynamicTableByteCount -= headerArr[length].hpackSize;
|
||||
this.headerCount--;
|
||||
i2++;
|
||||
}
|
||||
Header[] headerArr2 = this.dynamicTable;
|
||||
int i3 = this.nextHeaderIndex;
|
||||
System.arraycopy(headerArr2, i3 + 1, headerArr2, i3 + 1 + i2, this.headerCount);
|
||||
this.nextHeaderIndex += i2;
|
||||
}
|
||||
return i2;
|
||||
}
|
||||
|
||||
private ByteString getName(int i) throws IOException {
|
||||
if (isStaticHeader(i)) {
|
||||
return Hpack.STATIC_HEADER_TABLE[i].name;
|
||||
}
|
||||
int dynamicTableIndex = dynamicTableIndex(i - Hpack.STATIC_HEADER_TABLE.length);
|
||||
if (dynamicTableIndex >= 0) {
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
if (dynamicTableIndex < headerArr.length) {
|
||||
return headerArr[dynamicTableIndex].name;
|
||||
}
|
||||
}
|
||||
throw new IOException("Header index too large " + (i + 1));
|
||||
}
|
||||
|
||||
private void insertIntoDynamicTable(int i, Header header) {
|
||||
this.headerList.add(header);
|
||||
int i2 = header.hpackSize;
|
||||
if (i != -1) {
|
||||
i2 -= this.dynamicTable[dynamicTableIndex(i)].hpackSize;
|
||||
}
|
||||
int i3 = this.maxDynamicTableByteCount;
|
||||
if (i2 > i3) {
|
||||
clearDynamicTable();
|
||||
return;
|
||||
}
|
||||
int evictToRecoverBytes = evictToRecoverBytes((this.dynamicTableByteCount + i2) - i3);
|
||||
if (i == -1) {
|
||||
int i4 = this.headerCount + 1;
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
if (i4 > headerArr.length) {
|
||||
Header[] headerArr2 = new Header[headerArr.length * 2];
|
||||
System.arraycopy(headerArr, 0, headerArr2, headerArr.length, headerArr.length);
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.dynamicTable = headerArr2;
|
||||
}
|
||||
int i5 = this.nextHeaderIndex;
|
||||
this.nextHeaderIndex = i5 - 1;
|
||||
this.dynamicTable[i5] = header;
|
||||
this.headerCount++;
|
||||
} else {
|
||||
this.dynamicTable[i + dynamicTableIndex(i) + evictToRecoverBytes] = header;
|
||||
}
|
||||
this.dynamicTableByteCount += i2;
|
||||
}
|
||||
|
||||
private boolean isStaticHeader(int i) {
|
||||
return i >= 0 && i <= Hpack.STATIC_HEADER_TABLE.length - 1;
|
||||
}
|
||||
|
||||
private int readByte() throws IOException {
|
||||
return this.source.readByte() & 255;
|
||||
}
|
||||
|
||||
private void readIndexedHeader(int i) throws IOException {
|
||||
if (isStaticHeader(i)) {
|
||||
this.headerList.add(Hpack.STATIC_HEADER_TABLE[i]);
|
||||
return;
|
||||
}
|
||||
int dynamicTableIndex = dynamicTableIndex(i - Hpack.STATIC_HEADER_TABLE.length);
|
||||
if (dynamicTableIndex >= 0) {
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
if (dynamicTableIndex < headerArr.length) {
|
||||
this.headerList.add(headerArr[dynamicTableIndex]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IOException("Header index too large " + (i + 1));
|
||||
}
|
||||
|
||||
private void readLiteralHeaderWithIncrementalIndexingIndexedName(int i) throws IOException {
|
||||
insertIntoDynamicTable(-1, new Header(getName(i), readByteString()));
|
||||
}
|
||||
|
||||
private void readLiteralHeaderWithIncrementalIndexingNewName() throws IOException {
|
||||
insertIntoDynamicTable(-1, new Header(Hpack.checkLowercase(readByteString()), readByteString()));
|
||||
}
|
||||
|
||||
private void readLiteralHeaderWithoutIndexingIndexedName(int i) throws IOException {
|
||||
this.headerList.add(new Header(getName(i), readByteString()));
|
||||
}
|
||||
|
||||
private void readLiteralHeaderWithoutIndexingNewName() throws IOException {
|
||||
this.headerList.add(new Header(Hpack.checkLowercase(readByteString()), readByteString()));
|
||||
}
|
||||
|
||||
public List<Header> getAndResetHeaderList() {
|
||||
ArrayList arrayList = new ArrayList(this.headerList);
|
||||
this.headerList.clear();
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
int maxDynamicTableByteCount() {
|
||||
return this.maxDynamicTableByteCount;
|
||||
}
|
||||
|
||||
ByteString readByteString() throws IOException {
|
||||
int readByte = readByte();
|
||||
boolean z = (readByte & PeripheralType.SERVO) == 128;
|
||||
int readInt = readInt(readByte, Hpack.PREFIX_7_BITS);
|
||||
return z ? ByteString.of(Huffman.get().decode(this.source.readByteArray(readInt))) : this.source.readByteString(readInt);
|
||||
}
|
||||
|
||||
void readHeaders() throws IOException {
|
||||
while (!this.source.exhausted()) {
|
||||
int readByte = this.source.readByte() & 255;
|
||||
if (readByte == 128) {
|
||||
throw new IOException("index == 0");
|
||||
}
|
||||
if ((readByte & PeripheralType.SERVO) == 128) {
|
||||
readIndexedHeader(readInt(readByte, Hpack.PREFIX_7_BITS) - 1);
|
||||
} else if (readByte == 64) {
|
||||
readLiteralHeaderWithIncrementalIndexingNewName();
|
||||
} else if ((readByte & 64) == 64) {
|
||||
readLiteralHeaderWithIncrementalIndexingIndexedName(readInt(readByte, 63) - 1);
|
||||
} else if ((readByte & 32) == 32) {
|
||||
this.maxDynamicTableByteCount = readInt(readByte, 31);
|
||||
int i = this.maxDynamicTableByteCount;
|
||||
if (i < 0 || i > this.headerTableSizeSetting) {
|
||||
throw new IOException("Invalid dynamic table size update " + this.maxDynamicTableByteCount);
|
||||
}
|
||||
adjustDynamicTableByteCount();
|
||||
} else if (readByte == 16 || readByte == 0) {
|
||||
readLiteralHeaderWithoutIndexingNewName();
|
||||
} else {
|
||||
readLiteralHeaderWithoutIndexingIndexedName(readInt(readByte, 15) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int readInt(int i, int i2) throws IOException {
|
||||
int i3 = i & i2;
|
||||
if (i3 < i2) {
|
||||
return i3;
|
||||
}
|
||||
int i4 = 0;
|
||||
while (true) {
|
||||
int readByte = readByte();
|
||||
if ((readByte & PeripheralType.SERVO) == 0) {
|
||||
return i2 + (readByte << i4);
|
||||
}
|
||||
i2 += (readByte & Hpack.PREFIX_7_BITS) << i4;
|
||||
i4 += 7;
|
||||
}
|
||||
}
|
||||
|
||||
Reader(int i, int i2, Source source) {
|
||||
this.headerList = new ArrayList();
|
||||
this.dynamicTable = new Header[8];
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.headerCount = 0;
|
||||
this.dynamicTableByteCount = 0;
|
||||
this.headerTableSizeSetting = i;
|
||||
this.maxDynamicTableByteCount = i2;
|
||||
this.source = Okio.buffer(source);
|
||||
}
|
||||
}
|
||||
|
||||
static final class Writer {
|
||||
private static final int SETTINGS_HEADER_TABLE_SIZE = 4096;
|
||||
private static final int SETTINGS_HEADER_TABLE_SIZE_LIMIT = 16384;
|
||||
Header[] dynamicTable;
|
||||
int dynamicTableByteCount;
|
||||
private boolean emitDynamicTableSizeUpdate;
|
||||
int headerCount;
|
||||
int headerTableSizeSetting;
|
||||
int maxDynamicTableByteCount;
|
||||
int nextHeaderIndex;
|
||||
private final Buffer out;
|
||||
private int smallestHeaderTableSizeSetting;
|
||||
private final boolean useCompression;
|
||||
|
||||
Writer(Buffer buffer) {
|
||||
this(4096, true, buffer);
|
||||
}
|
||||
|
||||
private void adjustDynamicTableByteCount() {
|
||||
int i = this.maxDynamicTableByteCount;
|
||||
int i2 = this.dynamicTableByteCount;
|
||||
if (i < i2) {
|
||||
if (i == 0) {
|
||||
clearDynamicTable();
|
||||
} else {
|
||||
evictToRecoverBytes(i2 - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearDynamicTable() {
|
||||
Arrays.fill(this.dynamicTable, (Object) null);
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.headerCount = 0;
|
||||
this.dynamicTableByteCount = 0;
|
||||
}
|
||||
|
||||
private int evictToRecoverBytes(int i) {
|
||||
int i2 = 0;
|
||||
if (i > 0) {
|
||||
int length = this.dynamicTable.length;
|
||||
while (true) {
|
||||
length--;
|
||||
if (length < this.nextHeaderIndex || i <= 0) {
|
||||
break;
|
||||
}
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
i -= headerArr[length].hpackSize;
|
||||
this.dynamicTableByteCount -= headerArr[length].hpackSize;
|
||||
this.headerCount--;
|
||||
i2++;
|
||||
}
|
||||
Header[] headerArr2 = this.dynamicTable;
|
||||
int i3 = this.nextHeaderIndex;
|
||||
System.arraycopy(headerArr2, i3 + 1, headerArr2, i3 + 1 + i2, this.headerCount);
|
||||
Header[] headerArr3 = this.dynamicTable;
|
||||
int i4 = this.nextHeaderIndex;
|
||||
Arrays.fill(headerArr3, i4 + 1, i4 + 1 + i2, (Object) null);
|
||||
this.nextHeaderIndex += i2;
|
||||
}
|
||||
return i2;
|
||||
}
|
||||
|
||||
private void insertIntoDynamicTable(Header header) {
|
||||
int i = header.hpackSize;
|
||||
int i2 = this.maxDynamicTableByteCount;
|
||||
if (i > i2) {
|
||||
clearDynamicTable();
|
||||
return;
|
||||
}
|
||||
evictToRecoverBytes((this.dynamicTableByteCount + i) - i2);
|
||||
int i3 = this.headerCount + 1;
|
||||
Header[] headerArr = this.dynamicTable;
|
||||
if (i3 > headerArr.length) {
|
||||
Header[] headerArr2 = new Header[headerArr.length * 2];
|
||||
System.arraycopy(headerArr, 0, headerArr2, headerArr.length, headerArr.length);
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.dynamicTable = headerArr2;
|
||||
}
|
||||
int i4 = this.nextHeaderIndex;
|
||||
this.nextHeaderIndex = i4 - 1;
|
||||
this.dynamicTable[i4] = header;
|
||||
this.headerCount++;
|
||||
this.dynamicTableByteCount += i;
|
||||
}
|
||||
|
||||
void setHeaderTableSizeSetting(int i) {
|
||||
this.headerTableSizeSetting = i;
|
||||
int min = Math.min(i, SETTINGS_HEADER_TABLE_SIZE_LIMIT);
|
||||
int i2 = this.maxDynamicTableByteCount;
|
||||
if (i2 == min) {
|
||||
return;
|
||||
}
|
||||
if (min < i2) {
|
||||
this.smallestHeaderTableSizeSetting = Math.min(this.smallestHeaderTableSizeSetting, min);
|
||||
}
|
||||
this.emitDynamicTableSizeUpdate = true;
|
||||
this.maxDynamicTableByteCount = min;
|
||||
adjustDynamicTableByteCount();
|
||||
}
|
||||
|
||||
void writeByteString(ByteString byteString) throws IOException {
|
||||
if (!this.useCompression || Huffman.get().encodedLength(byteString) >= byteString.size()) {
|
||||
writeInt(byteString.size(), Hpack.PREFIX_7_BITS, 0);
|
||||
this.out.write(byteString);
|
||||
return;
|
||||
}
|
||||
Buffer buffer = new Buffer();
|
||||
Huffman.get().encode(byteString, buffer);
|
||||
ByteString readByteString = buffer.readByteString();
|
||||
writeInt(readByteString.size(), Hpack.PREFIX_7_BITS, PeripheralType.SERVO);
|
||||
this.out.write(readByteString);
|
||||
}
|
||||
|
||||
void writeHeaders(List<Header> list) throws IOException {
|
||||
int i;
|
||||
int i2;
|
||||
if (this.emitDynamicTableSizeUpdate) {
|
||||
int i3 = this.smallestHeaderTableSizeSetting;
|
||||
if (i3 < this.maxDynamicTableByteCount) {
|
||||
writeInt(i3, 31, 32);
|
||||
}
|
||||
this.emitDynamicTableSizeUpdate = false;
|
||||
this.smallestHeaderTableSizeSetting = Integer.MAX_VALUE;
|
||||
writeInt(this.maxDynamicTableByteCount, 31, 32);
|
||||
}
|
||||
int size = list.size();
|
||||
for (int i4 = 0; i4 < size; i4++) {
|
||||
Header header = list.get(i4);
|
||||
ByteString asciiLowercase = header.name.toAsciiLowercase();
|
||||
ByteString byteString = header.value;
|
||||
Integer num = Hpack.NAME_TO_FIRST_INDEX.get(asciiLowercase);
|
||||
if (num != null) {
|
||||
i = num.intValue() + 1;
|
||||
if (i > 1 && i < 8) {
|
||||
if (Util.equal(Hpack.STATIC_HEADER_TABLE[i - 1].value, byteString)) {
|
||||
i2 = i;
|
||||
} else if (Util.equal(Hpack.STATIC_HEADER_TABLE[i].value, byteString)) {
|
||||
i2 = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i2 = i;
|
||||
i = -1;
|
||||
} else {
|
||||
i = -1;
|
||||
i2 = -1;
|
||||
}
|
||||
if (i == -1) {
|
||||
int i5 = this.nextHeaderIndex + 1;
|
||||
int length = this.dynamicTable.length;
|
||||
while (true) {
|
||||
if (i5 >= length) {
|
||||
break;
|
||||
}
|
||||
if (Util.equal(this.dynamicTable[i5].name, asciiLowercase)) {
|
||||
if (Util.equal(this.dynamicTable[i5].value, byteString)) {
|
||||
i = Hpack.STATIC_HEADER_TABLE.length + (i5 - this.nextHeaderIndex);
|
||||
break;
|
||||
} else if (i2 == -1) {
|
||||
i2 = (i5 - this.nextHeaderIndex) + Hpack.STATIC_HEADER_TABLE.length;
|
||||
}
|
||||
}
|
||||
i5++;
|
||||
}
|
||||
}
|
||||
if (i != -1) {
|
||||
writeInt(i, Hpack.PREFIX_7_BITS, PeripheralType.SERVO);
|
||||
} else if (i2 == -1) {
|
||||
this.out.writeByte(64);
|
||||
writeByteString(asciiLowercase);
|
||||
writeByteString(byteString);
|
||||
insertIntoDynamicTable(header);
|
||||
} else if (!asciiLowercase.startsWith(Header.PSEUDO_PREFIX) || Header.TARGET_AUTHORITY.equals(asciiLowercase)) {
|
||||
writeInt(i2, 63, 64);
|
||||
writeByteString(byteString);
|
||||
insertIntoDynamicTable(header);
|
||||
} else {
|
||||
writeInt(i2, 15, 0);
|
||||
writeByteString(byteString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeInt(int i, int i2, int i3) {
|
||||
if (i < i2) {
|
||||
this.out.writeByte(i | i3);
|
||||
return;
|
||||
}
|
||||
this.out.writeByte(i3 | i2);
|
||||
int i4 = i - i2;
|
||||
while (i4 >= 128) {
|
||||
this.out.writeByte(128 | (i4 & Hpack.PREFIX_7_BITS));
|
||||
i4 >>>= 7;
|
||||
}
|
||||
this.out.writeByte(i4);
|
||||
}
|
||||
|
||||
Writer(int i, boolean z, Buffer buffer) {
|
||||
this.smallestHeaderTableSizeSetting = Integer.MAX_VALUE;
|
||||
this.dynamicTable = new Header[8];
|
||||
this.nextHeaderIndex = this.dynamicTable.length - 1;
|
||||
this.headerCount = 0;
|
||||
this.dynamicTableByteCount = 0;
|
||||
this.headerTableSizeSetting = i;
|
||||
this.maxDynamicTableByteCount = i;
|
||||
this.useCompression = z;
|
||||
this.out = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
private Hpack() {
|
||||
}
|
||||
|
||||
static ByteString checkLowercase(ByteString byteString) throws IOException {
|
||||
int size = byteString.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
byte b = byteString.getByte(i);
|
||||
if (b >= 65 && b <= 90) {
|
||||
throw new IOException("PROTOCOL_ERROR response malformed: mixed case name: " + byteString.utf8());
|
||||
}
|
||||
}
|
||||
return byteString;
|
||||
}
|
||||
|
||||
private static Map<ByteString, Integer> nameToFirstIndex() {
|
||||
LinkedHashMap linkedHashMap = new LinkedHashMap(STATIC_HEADER_TABLE.length);
|
||||
int i = 0;
|
||||
while (true) {
|
||||
Header[] headerArr = STATIC_HEADER_TABLE;
|
||||
if (i >= headerArr.length) {
|
||||
return Collections.unmodifiableMap(linkedHashMap);
|
||||
}
|
||||
if (!linkedHashMap.containsKey(headerArr[i].name)) {
|
||||
linkedHashMap.put(STATIC_HEADER_TABLE[i].name, Integer.valueOf(i));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
116
sources/okhttp3/internal/http2/Http2.java
Normal file
116
sources/okhttp3/internal/http2/Http2.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import com.ijm.dataencryption.de.DataDecryptTool;
|
||||
import java.io.IOException;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Http2 {
|
||||
static final byte FLAG_ACK = 1;
|
||||
static final byte FLAG_COMPRESSED = 32;
|
||||
static final byte FLAG_END_HEADERS = 4;
|
||||
static final byte FLAG_END_PUSH_PROMISE = 4;
|
||||
static final byte FLAG_END_STREAM = 1;
|
||||
static final byte FLAG_NONE = 0;
|
||||
static final byte FLAG_PADDED = 8;
|
||||
static final byte FLAG_PRIORITY = 32;
|
||||
static final int INITIAL_MAX_FRAME_SIZE = 16384;
|
||||
static final byte TYPE_CONTINUATION = 9;
|
||||
static final byte TYPE_DATA = 0;
|
||||
static final byte TYPE_GOAWAY = 7;
|
||||
static final byte TYPE_HEADERS = 1;
|
||||
static final byte TYPE_PING = 6;
|
||||
static final byte TYPE_PRIORITY = 2;
|
||||
static final byte TYPE_PUSH_PROMISE = 5;
|
||||
static final byte TYPE_RST_STREAM = 3;
|
||||
static final byte TYPE_SETTINGS = 4;
|
||||
static final byte TYPE_WINDOW_UPDATE = 8;
|
||||
static final ByteString CONNECTION_PREFACE = ByteString.encodeUtf8("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
|
||||
private static final String[] FRAME_NAMES = {"DATA", "HEADERS", "PRIORITY", "RST_STREAM", "SETTINGS", "PUSH_PROMISE", "PING", "GOAWAY", "WINDOW_UPDATE", "CONTINUATION"};
|
||||
static final String[] FLAGS = new String[64];
|
||||
static final String[] BINARY = new String[DataDecryptTool.DECRYPT_ALL_FILE];
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
int i2 = 0;
|
||||
while (true) {
|
||||
String[] strArr = BINARY;
|
||||
if (i2 >= strArr.length) {
|
||||
break;
|
||||
}
|
||||
strArr[i2] = Util.format("%8s", Integer.toBinaryString(i2)).replace(' ', '0');
|
||||
i2++;
|
||||
}
|
||||
String[] strArr2 = FLAGS;
|
||||
strArr2[0] = "";
|
||||
strArr2[1] = "END_STREAM";
|
||||
int[] iArr = {1};
|
||||
strArr2[8] = "PADDED";
|
||||
for (int i3 : iArr) {
|
||||
FLAGS[i3 | 8] = FLAGS[i3] + "|PADDED";
|
||||
}
|
||||
String[] strArr3 = FLAGS;
|
||||
strArr3[4] = "END_HEADERS";
|
||||
strArr3[32] = "PRIORITY";
|
||||
strArr3[36] = "END_HEADERS|PRIORITY";
|
||||
for (int i4 : new int[]{4, 32, 36}) {
|
||||
for (int i5 : iArr) {
|
||||
int i6 = i5 | i4;
|
||||
FLAGS[i6] = FLAGS[i5] + '|' + FLAGS[i4];
|
||||
FLAGS[i6 | 8] = FLAGS[i5] + '|' + FLAGS[i4] + "|PADDED";
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
String[] strArr4 = FLAGS;
|
||||
if (i >= strArr4.length) {
|
||||
return;
|
||||
}
|
||||
if (strArr4[i] == null) {
|
||||
strArr4[i] = BINARY[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private Http2() {
|
||||
}
|
||||
|
||||
static String formatFlags(byte b, byte b2) {
|
||||
if (b2 == 0) {
|
||||
return "";
|
||||
}
|
||||
if (b != 2 && b != 3) {
|
||||
if (b == 4 || b == 6) {
|
||||
return b2 == 1 ? "ACK" : BINARY[b2];
|
||||
}
|
||||
if (b != 7 && b != 8) {
|
||||
String[] strArr = FLAGS;
|
||||
String str = b2 < strArr.length ? strArr[b2] : BINARY[b2];
|
||||
return (b != 5 || (b2 & 4) == 0) ? (b != 0 || (b2 & 32) == 0) ? str : str.replace("PRIORITY", "COMPRESSED") : str.replace("HEADERS", "PUSH_PROMISE");
|
||||
}
|
||||
}
|
||||
return BINARY[b2];
|
||||
}
|
||||
|
||||
static String frameLog(boolean z, int i, int i2, byte b, byte b2) {
|
||||
String[] strArr = FRAME_NAMES;
|
||||
String format = b < strArr.length ? strArr[b] : Util.format("0x%02x", Byte.valueOf(b));
|
||||
String formatFlags = formatFlags(b, b2);
|
||||
Object[] objArr = new Object[5];
|
||||
objArr[0] = z ? "<<" : ">>";
|
||||
objArr[1] = Integer.valueOf(i);
|
||||
objArr[2] = Integer.valueOf(i2);
|
||||
objArr[3] = format;
|
||||
objArr[4] = formatFlags;
|
||||
return Util.format("%s 0x%08x %5d %-13s %s", objArr);
|
||||
}
|
||||
|
||||
static IllegalArgumentException illegalArgument(String str, Object... objArr) {
|
||||
throw new IllegalArgumentException(Util.format(str, objArr));
|
||||
}
|
||||
|
||||
static IOException ioException(String str, Object... objArr) throws IOException {
|
||||
throw new IOException(Util.format(str, objArr));
|
||||
}
|
||||
}
|
||||
190
sources/okhttp3/internal/http2/Http2Codec.java
Normal file
190
sources/okhttp3/internal/http2/Http2Codec.java
Normal file
@@ -0,0 +1,190 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
import okhttp3.internal.http.HttpCodec;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.http.RealResponseBody;
|
||||
import okhttp3.internal.http.RequestLine;
|
||||
import okhttp3.internal.http.StatusLine;
|
||||
import okio.Buffer;
|
||||
import okio.ByteString;
|
||||
import okio.ForwardingSource;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Http2Codec implements HttpCodec {
|
||||
private final Interceptor.Chain chain;
|
||||
private final Http2Connection connection;
|
||||
private final Protocol protocol;
|
||||
private Http2Stream stream;
|
||||
final StreamAllocation streamAllocation;
|
||||
private static final ByteString CONNECTION = ByteString.encodeUtf8("connection");
|
||||
private static final ByteString HOST = ByteString.encodeUtf8("host");
|
||||
private static final ByteString KEEP_ALIVE = ByteString.encodeUtf8("keep-alive");
|
||||
private static final ByteString PROXY_CONNECTION = ByteString.encodeUtf8("proxy-connection");
|
||||
private static final ByteString TRANSFER_ENCODING = ByteString.encodeUtf8("transfer-encoding");
|
||||
private static final ByteString TE = ByteString.encodeUtf8("te");
|
||||
private static final ByteString ENCODING = ByteString.encodeUtf8("encoding");
|
||||
private static final ByteString UPGRADE = ByteString.encodeUtf8("upgrade");
|
||||
private static final List<ByteString> HTTP_2_SKIPPED_REQUEST_HEADERS = Util.immutableList(CONNECTION, HOST, KEEP_ALIVE, PROXY_CONNECTION, TE, TRANSFER_ENCODING, ENCODING, UPGRADE, Header.TARGET_METHOD, Header.TARGET_PATH, Header.TARGET_SCHEME, Header.TARGET_AUTHORITY);
|
||||
private static final List<ByteString> HTTP_2_SKIPPED_RESPONSE_HEADERS = Util.immutableList(CONNECTION, HOST, KEEP_ALIVE, PROXY_CONNECTION, TE, TRANSFER_ENCODING, ENCODING, UPGRADE);
|
||||
|
||||
class StreamFinishingSource extends ForwardingSource {
|
||||
long bytesRead;
|
||||
boolean completed;
|
||||
|
||||
StreamFinishingSource(Source source) {
|
||||
super(source);
|
||||
this.completed = false;
|
||||
this.bytesRead = 0L;
|
||||
}
|
||||
|
||||
private void endOfInput(IOException iOException) {
|
||||
if (this.completed) {
|
||||
return;
|
||||
}
|
||||
this.completed = true;
|
||||
Http2Codec http2Codec = Http2Codec.this;
|
||||
http2Codec.streamAllocation.streamFinished(false, http2Codec, this.bytesRead, iOException);
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSource, okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
endOfInput(null);
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSource, okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
try {
|
||||
long read = delegate().read(buffer, j);
|
||||
if (read > 0) {
|
||||
this.bytesRead += read;
|
||||
}
|
||||
return read;
|
||||
} catch (IOException e) {
|
||||
endOfInput(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Http2Codec(OkHttpClient okHttpClient, Interceptor.Chain chain, StreamAllocation streamAllocation, Http2Connection http2Connection) {
|
||||
this.chain = chain;
|
||||
this.streamAllocation = streamAllocation;
|
||||
this.connection = http2Connection;
|
||||
this.protocol = okHttpClient.protocols().contains(Protocol.H2_PRIOR_KNOWLEDGE) ? Protocol.H2_PRIOR_KNOWLEDGE : Protocol.HTTP_2;
|
||||
}
|
||||
|
||||
public static List<Header> http2HeadersList(Request request) {
|
||||
Headers headers = request.headers();
|
||||
ArrayList arrayList = new ArrayList(headers.size() + 4);
|
||||
arrayList.add(new Header(Header.TARGET_METHOD, request.method()));
|
||||
arrayList.add(new Header(Header.TARGET_PATH, RequestLine.requestPath(request.url())));
|
||||
String header = request.header("Host");
|
||||
if (header != null) {
|
||||
arrayList.add(new Header(Header.TARGET_AUTHORITY, header));
|
||||
}
|
||||
arrayList.add(new Header(Header.TARGET_SCHEME, request.url().scheme()));
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
ByteString encodeUtf8 = ByteString.encodeUtf8(headers.name(i).toLowerCase(Locale.US));
|
||||
if (!HTTP_2_SKIPPED_REQUEST_HEADERS.contains(encodeUtf8)) {
|
||||
arrayList.add(new Header(encodeUtf8, headers.value(i)));
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
public static Response.Builder readHttp2HeadersList(List<Header> list, Protocol protocol) throws IOException {
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
int size = list.size();
|
||||
Headers.Builder builder2 = builder;
|
||||
StatusLine statusLine = null;
|
||||
for (int i = 0; i < size; i++) {
|
||||
Header header = list.get(i);
|
||||
if (header != null) {
|
||||
ByteString byteString = header.name;
|
||||
String utf8 = header.value.utf8();
|
||||
if (byteString.equals(Header.RESPONSE_STATUS)) {
|
||||
statusLine = StatusLine.parse("HTTP/1.1 " + utf8);
|
||||
} else if (!HTTP_2_SKIPPED_RESPONSE_HEADERS.contains(byteString)) {
|
||||
Internal.instance.addLenient(builder2, byteString.utf8(), utf8);
|
||||
}
|
||||
} else if (statusLine != null && statusLine.code == 100) {
|
||||
builder2 = new Headers.Builder();
|
||||
statusLine = null;
|
||||
}
|
||||
}
|
||||
if (statusLine != null) {
|
||||
return new Response.Builder().protocol(protocol).code(statusLine.code).message(statusLine.message).headers(builder2.build());
|
||||
}
|
||||
throw new ProtocolException("Expected ':status' header not present");
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void cancel() {
|
||||
Http2Stream http2Stream = this.stream;
|
||||
if (http2Stream != null) {
|
||||
http2Stream.closeLater(ErrorCode.CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public Sink createRequestBody(Request request, long j) {
|
||||
return this.stream.getSink();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void finishRequest() throws IOException {
|
||||
this.stream.getSink().close();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void flushRequest() throws IOException {
|
||||
this.connection.flush();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public ResponseBody openResponseBody(Response response) throws IOException {
|
||||
StreamAllocation streamAllocation = this.streamAllocation;
|
||||
streamAllocation.eventListener.responseBodyStart(streamAllocation.call);
|
||||
return new RealResponseBody(response.header("Content-Type"), HttpHeaders.contentLength(response), Okio.buffer(new StreamFinishingSource(this.stream.getSource())));
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public Response.Builder readResponseHeaders(boolean z) throws IOException {
|
||||
Response.Builder readHttp2HeadersList = readHttp2HeadersList(this.stream.takeResponseHeaders(), this.protocol);
|
||||
if (z && Internal.instance.code(readHttp2HeadersList) == 100) {
|
||||
return null;
|
||||
}
|
||||
return readHttp2HeadersList;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http.HttpCodec
|
||||
public void writeRequestHeaders(Request request) throws IOException {
|
||||
if (this.stream != null) {
|
||||
return;
|
||||
}
|
||||
this.stream = this.connection.newStream(http2HeadersList(request), request.body() != null);
|
||||
this.stream.readTimeout().timeout(this.chain.readTimeoutMillis(), TimeUnit.MILLISECONDS);
|
||||
this.stream.writeTimeout().timeout(this.chain.writeTimeoutMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
853
sources/okhttp3/internal/http2/Http2Connection.java
Normal file
853
sources/okhttp3/internal/http2/Http2Connection.java
Normal file
@@ -0,0 +1,853 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.internal.NamedRunnable;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.http2.Http2Reader;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
import okio.Okio;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Http2Connection implements Closeable {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
static final int OKHTTP_CLIENT_WINDOW_SIZE = 16777216;
|
||||
private static final ExecutorService listenerExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue(), Util.threadFactory("OkHttp Http2Connection", true));
|
||||
private boolean awaitingPong;
|
||||
long bytesLeftInWriteWindow;
|
||||
final boolean client;
|
||||
final String hostname;
|
||||
int lastGoodStreamId;
|
||||
final Listener listener;
|
||||
int nextStreamId;
|
||||
private final ExecutorService pushExecutor;
|
||||
final PushObserver pushObserver;
|
||||
final ReaderRunnable readerRunnable;
|
||||
boolean shutdown;
|
||||
final Socket socket;
|
||||
final Http2Writer writer;
|
||||
private final ScheduledExecutorService writerExecutor;
|
||||
final Map<Integer, Http2Stream> streams = new LinkedHashMap();
|
||||
long unacknowledgedBytesRead = 0;
|
||||
Settings okHttpSettings = new Settings();
|
||||
final Settings peerSettings = new Settings();
|
||||
boolean receivedInitialPeerSettings = false;
|
||||
final Set<Integer> currentPushRequests = new LinkedHashSet();
|
||||
|
||||
public static abstract class Listener {
|
||||
public static final Listener REFUSE_INCOMING_STREAMS = new Listener() { // from class: okhttp3.internal.http2.Http2Connection.Listener.1
|
||||
@Override // okhttp3.internal.http2.Http2Connection.Listener
|
||||
public void onStream(Http2Stream http2Stream) throws IOException {
|
||||
http2Stream.close(ErrorCode.REFUSED_STREAM);
|
||||
}
|
||||
};
|
||||
|
||||
public void onSettings(Http2Connection http2Connection) {
|
||||
}
|
||||
|
||||
public abstract void onStream(Http2Stream http2Stream) throws IOException;
|
||||
}
|
||||
|
||||
final class PingRunnable extends NamedRunnable {
|
||||
final int payload1;
|
||||
final int payload2;
|
||||
final boolean reply;
|
||||
|
||||
PingRunnable(boolean z, int i, int i2) {
|
||||
super("OkHttp %s ping %08x%08x", Http2Connection.this.hostname, Integer.valueOf(i), Integer.valueOf(i2));
|
||||
this.reply = z;
|
||||
this.payload1 = i;
|
||||
this.payload2 = i2;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
Http2Connection.this.writePing(this.reply, this.payload1, this.payload2);
|
||||
}
|
||||
}
|
||||
|
||||
class ReaderRunnable extends NamedRunnable implements Http2Reader.Handler {
|
||||
final Http2Reader reader;
|
||||
|
||||
ReaderRunnable(Http2Reader http2Reader) {
|
||||
super("OkHttp %s", Http2Connection.this.hostname);
|
||||
this.reader = http2Reader;
|
||||
}
|
||||
|
||||
private void applyAndAckSettings(final Settings settings) {
|
||||
try {
|
||||
Http2Connection.this.writerExecutor.execute(new NamedRunnable("OkHttp %s ACK Settings", new Object[]{Http2Connection.this.hostname}) { // from class: okhttp3.internal.http2.Http2Connection.ReaderRunnable.3
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
try {
|
||||
Http2Connection.this.writer.applyAndAckSettings(settings);
|
||||
} catch (IOException unused) {
|
||||
Http2Connection.this.failConnection();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void ackSettings() {
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void alternateService(int i, String str, ByteString byteString, String str2, int i2, long j) {
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void data(boolean z, int i, BufferedSource bufferedSource, int i2) throws IOException {
|
||||
if (Http2Connection.this.pushedStream(i)) {
|
||||
Http2Connection.this.pushDataLater(i, bufferedSource, i2, z);
|
||||
return;
|
||||
}
|
||||
Http2Stream stream = Http2Connection.this.getStream(i);
|
||||
if (stream == null) {
|
||||
Http2Connection.this.writeSynResetLater(i, ErrorCode.PROTOCOL_ERROR);
|
||||
long j = i2;
|
||||
Http2Connection.this.updateConnectionFlowControl(j);
|
||||
bufferedSource.skip(j);
|
||||
return;
|
||||
}
|
||||
stream.receiveData(bufferedSource, i2);
|
||||
if (z) {
|
||||
stream.receiveFin();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
protected void execute() {
|
||||
ErrorCode errorCode;
|
||||
Http2Connection http2Connection;
|
||||
ErrorCode errorCode2 = ErrorCode.INTERNAL_ERROR;
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
this.reader.readConnectionPreface(this);
|
||||
while (this.reader.nextFrame(false, this)) {
|
||||
}
|
||||
errorCode = ErrorCode.NO_ERROR;
|
||||
} catch (IOException unused) {
|
||||
} catch (Throwable th) {
|
||||
th = th;
|
||||
errorCode = errorCode2;
|
||||
try {
|
||||
Http2Connection.this.close(errorCode, errorCode2);
|
||||
} catch (IOException unused2) {
|
||||
}
|
||||
Util.closeQuietly(this.reader);
|
||||
throw th;
|
||||
}
|
||||
try {
|
||||
errorCode2 = ErrorCode.CANCEL;
|
||||
http2Connection = Http2Connection.this;
|
||||
} catch (IOException unused3) {
|
||||
errorCode = ErrorCode.PROTOCOL_ERROR;
|
||||
errorCode2 = ErrorCode.PROTOCOL_ERROR;
|
||||
http2Connection = Http2Connection.this;
|
||||
http2Connection.close(errorCode, errorCode2);
|
||||
Util.closeQuietly(this.reader);
|
||||
}
|
||||
http2Connection.close(errorCode, errorCode2);
|
||||
} catch (IOException unused4) {
|
||||
}
|
||||
Util.closeQuietly(this.reader);
|
||||
} catch (Throwable th2) {
|
||||
th = th2;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void goAway(int i, ErrorCode errorCode, ByteString byteString) {
|
||||
Http2Stream[] http2StreamArr;
|
||||
byteString.size();
|
||||
synchronized (Http2Connection.this) {
|
||||
http2StreamArr = (Http2Stream[]) Http2Connection.this.streams.values().toArray(new Http2Stream[Http2Connection.this.streams.size()]);
|
||||
Http2Connection.this.shutdown = true;
|
||||
}
|
||||
for (Http2Stream http2Stream : http2StreamArr) {
|
||||
if (http2Stream.getId() > i && http2Stream.isLocallyInitiated()) {
|
||||
http2Stream.receiveRstStream(ErrorCode.REFUSED_STREAM);
|
||||
Http2Connection.this.removeStream(http2Stream.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void headers(boolean z, int i, int i2, List<Header> list) {
|
||||
if (Http2Connection.this.pushedStream(i)) {
|
||||
Http2Connection.this.pushHeadersLater(i, list, z);
|
||||
return;
|
||||
}
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Stream stream = Http2Connection.this.getStream(i);
|
||||
if (stream != null) {
|
||||
stream.receiveHeaders(list);
|
||||
if (z) {
|
||||
stream.receiveFin();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Http2Connection.this.shutdown) {
|
||||
return;
|
||||
}
|
||||
if (i <= Http2Connection.this.lastGoodStreamId) {
|
||||
return;
|
||||
}
|
||||
if (i % 2 == Http2Connection.this.nextStreamId % 2) {
|
||||
return;
|
||||
}
|
||||
final Http2Stream http2Stream = new Http2Stream(i, Http2Connection.this, false, z, list);
|
||||
Http2Connection.this.lastGoodStreamId = i;
|
||||
Http2Connection.this.streams.put(Integer.valueOf(i), http2Stream);
|
||||
Http2Connection.listenerExecutor.execute(new NamedRunnable("OkHttp %s stream %d", new Object[]{Http2Connection.this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.ReaderRunnable.1
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
try {
|
||||
Http2Connection.this.listener.onStream(http2Stream);
|
||||
} catch (IOException e) {
|
||||
Platform.get().log(4, "Http2Connection.Listener failure for " + Http2Connection.this.hostname, e);
|
||||
try {
|
||||
http2Stream.close(ErrorCode.PROTOCOL_ERROR);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void ping(boolean z, int i, int i2) {
|
||||
if (!z) {
|
||||
try {
|
||||
Http2Connection.this.writerExecutor.execute(Http2Connection.this.new PingRunnable(true, i, i2));
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
} else {
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.awaitingPong = false;
|
||||
Http2Connection.this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void priority(int i, int i2, int i3, boolean z) {
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void pushPromise(int i, int i2, List<Header> list) {
|
||||
Http2Connection.this.pushRequestLater(i2, list);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void rstStream(int i, ErrorCode errorCode) {
|
||||
if (Http2Connection.this.pushedStream(i)) {
|
||||
Http2Connection.this.pushResetLater(i, errorCode);
|
||||
return;
|
||||
}
|
||||
Http2Stream removeStream = Http2Connection.this.removeStream(i);
|
||||
if (removeStream != null) {
|
||||
removeStream.receiveRstStream(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void settings(boolean z, Settings settings) {
|
||||
Http2Stream[] http2StreamArr;
|
||||
long j;
|
||||
int i;
|
||||
synchronized (Http2Connection.this) {
|
||||
int initialWindowSize = Http2Connection.this.peerSettings.getInitialWindowSize();
|
||||
if (z) {
|
||||
Http2Connection.this.peerSettings.clear();
|
||||
}
|
||||
Http2Connection.this.peerSettings.merge(settings);
|
||||
applyAndAckSettings(settings);
|
||||
int initialWindowSize2 = Http2Connection.this.peerSettings.getInitialWindowSize();
|
||||
http2StreamArr = null;
|
||||
if (initialWindowSize2 == -1 || initialWindowSize2 == initialWindowSize) {
|
||||
j = 0;
|
||||
} else {
|
||||
j = initialWindowSize2 - initialWindowSize;
|
||||
if (!Http2Connection.this.receivedInitialPeerSettings) {
|
||||
Http2Connection.this.receivedInitialPeerSettings = true;
|
||||
}
|
||||
if (!Http2Connection.this.streams.isEmpty()) {
|
||||
http2StreamArr = (Http2Stream[]) Http2Connection.this.streams.values().toArray(new Http2Stream[Http2Connection.this.streams.size()]);
|
||||
}
|
||||
}
|
||||
Http2Connection.listenerExecutor.execute(new NamedRunnable("OkHttp %s settings", Http2Connection.this.hostname) { // from class: okhttp3.internal.http2.Http2Connection.ReaderRunnable.2
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
Http2Connection http2Connection = Http2Connection.this;
|
||||
http2Connection.listener.onSettings(http2Connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (http2StreamArr == null || j == 0) {
|
||||
return;
|
||||
}
|
||||
for (Http2Stream http2Stream : http2StreamArr) {
|
||||
synchronized (http2Stream) {
|
||||
http2Stream.addBytesToWriteWindow(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.Http2Reader.Handler
|
||||
public void windowUpdate(int i, long j) {
|
||||
if (i == 0) {
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.bytesLeftInWriteWindow += j;
|
||||
Http2Connection.this.notifyAll();
|
||||
}
|
||||
return;
|
||||
}
|
||||
Http2Stream stream = Http2Connection.this.getStream(i);
|
||||
if (stream != null) {
|
||||
synchronized (stream) {
|
||||
stream.addBytesToWriteWindow(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Http2Connection(Builder builder) {
|
||||
this.pushObserver = builder.pushObserver;
|
||||
boolean z = builder.client;
|
||||
this.client = z;
|
||||
this.listener = builder.listener;
|
||||
this.nextStreamId = z ? 1 : 2;
|
||||
if (builder.client) {
|
||||
this.nextStreamId += 2;
|
||||
}
|
||||
if (builder.client) {
|
||||
this.okHttpSettings.set(7, OKHTTP_CLIENT_WINDOW_SIZE);
|
||||
}
|
||||
this.hostname = builder.hostname;
|
||||
this.writerExecutor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(Util.format("OkHttp %s Writer", this.hostname), false));
|
||||
if (builder.pingIntervalMillis != 0) {
|
||||
ScheduledExecutorService scheduledExecutorService = this.writerExecutor;
|
||||
PingRunnable pingRunnable = new PingRunnable(false, 0, 0);
|
||||
int i = builder.pingIntervalMillis;
|
||||
scheduledExecutorService.scheduleAtFixedRate(pingRunnable, i, i, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
this.pushExecutor = new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(), Util.threadFactory(Util.format("OkHttp %s Push Observer", this.hostname), true));
|
||||
this.peerSettings.set(7, 65535);
|
||||
this.peerSettings.set(5, 16384);
|
||||
this.bytesLeftInWriteWindow = this.peerSettings.getInitialWindowSize();
|
||||
this.socket = builder.socket;
|
||||
this.writer = new Http2Writer(builder.sink, this.client);
|
||||
this.readerRunnable = new ReaderRunnable(new Http2Reader(builder.source, this.client));
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public void failConnection() {
|
||||
try {
|
||||
close(ErrorCode.PROTOCOL_ERROR, ErrorCode.PROTOCOL_ERROR);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void pushExecutorExecute(NamedRunnable namedRunnable) {
|
||||
if (!isShutdown()) {
|
||||
this.pushExecutor.execute(namedRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void awaitPong() throws InterruptedException {
|
||||
while (this.awaitingPong) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
close(ErrorCode.NO_ERROR, ErrorCode.CANCEL);
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
this.writer.flush();
|
||||
}
|
||||
|
||||
public Protocol getProtocol() {
|
||||
return Protocol.HTTP_2;
|
||||
}
|
||||
|
||||
synchronized Http2Stream getStream(int i) {
|
||||
return this.streams.get(Integer.valueOf(i));
|
||||
}
|
||||
|
||||
public synchronized boolean isShutdown() {
|
||||
return this.shutdown;
|
||||
}
|
||||
|
||||
public synchronized int maxConcurrentStreams() {
|
||||
return this.peerSettings.getMaxConcurrentStreams(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public Http2Stream newStream(List<Header> list, boolean z) throws IOException {
|
||||
return newStream(0, list, z);
|
||||
}
|
||||
|
||||
public synchronized int openStreamCount() {
|
||||
return this.streams.size();
|
||||
}
|
||||
|
||||
void pushDataLater(final int i, BufferedSource bufferedSource, final int i2, final boolean z) throws IOException {
|
||||
final Buffer buffer = new Buffer();
|
||||
long j = i2;
|
||||
bufferedSource.require(j);
|
||||
bufferedSource.read(buffer, j);
|
||||
if (buffer.size() == j) {
|
||||
pushExecutorExecute(new NamedRunnable("OkHttp %s Push Data[%s]", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.5
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
try {
|
||||
boolean onData = Http2Connection.this.pushObserver.onData(i, buffer, i2, z);
|
||||
if (onData) {
|
||||
Http2Connection.this.writer.rstStream(i, ErrorCode.CANCEL);
|
||||
}
|
||||
if (onData || z) {
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.currentPushRequests.remove(Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
throw new IOException(buffer.size() + " != " + i2);
|
||||
}
|
||||
|
||||
void pushHeadersLater(final int i, final List<Header> list, final boolean z) {
|
||||
try {
|
||||
pushExecutorExecute(new NamedRunnable("OkHttp %s Push Headers[%s]", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.4
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
boolean onHeaders = Http2Connection.this.pushObserver.onHeaders(i, list, z);
|
||||
if (onHeaders) {
|
||||
try {
|
||||
Http2Connection.this.writer.rstStream(i, ErrorCode.CANCEL);
|
||||
} catch (IOException unused) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (onHeaders || z) {
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.currentPushRequests.remove(Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
}
|
||||
|
||||
void pushRequestLater(final int i, final List<Header> list) {
|
||||
synchronized (this) {
|
||||
if (this.currentPushRequests.contains(Integer.valueOf(i))) {
|
||||
writeSynResetLater(i, ErrorCode.PROTOCOL_ERROR);
|
||||
return;
|
||||
}
|
||||
this.currentPushRequests.add(Integer.valueOf(i));
|
||||
try {
|
||||
pushExecutorExecute(new NamedRunnable("OkHttp %s Push Request[%s]", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.3
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
if (Http2Connection.this.pushObserver.onRequest(i, list)) {
|
||||
try {
|
||||
Http2Connection.this.writer.rstStream(i, ErrorCode.CANCEL);
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.currentPushRequests.remove(Integer.valueOf(i));
|
||||
}
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pushResetLater(final int i, final ErrorCode errorCode) {
|
||||
pushExecutorExecute(new NamedRunnable("OkHttp %s Push Reset[%s]", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.6
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
Http2Connection.this.pushObserver.onReset(i, errorCode);
|
||||
synchronized (Http2Connection.this) {
|
||||
Http2Connection.this.currentPushRequests.remove(Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Http2Stream pushStream(int i, List<Header> list, boolean z) throws IOException {
|
||||
if (this.client) {
|
||||
throw new IllegalStateException("Client cannot push requests.");
|
||||
}
|
||||
return newStream(i, list, z);
|
||||
}
|
||||
|
||||
boolean pushedStream(int i) {
|
||||
return i != 0 && (i & 1) == 0;
|
||||
}
|
||||
|
||||
synchronized Http2Stream removeStream(int i) {
|
||||
Http2Stream remove;
|
||||
remove = this.streams.remove(Integer.valueOf(i));
|
||||
notifyAll();
|
||||
return remove;
|
||||
}
|
||||
|
||||
public void setSettings(Settings settings) throws IOException {
|
||||
synchronized (this.writer) {
|
||||
synchronized (this) {
|
||||
if (this.shutdown) {
|
||||
throw new ConnectionShutdownException();
|
||||
}
|
||||
this.okHttpSettings.merge(settings);
|
||||
}
|
||||
this.writer.settings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown(ErrorCode errorCode) throws IOException {
|
||||
synchronized (this.writer) {
|
||||
synchronized (this) {
|
||||
if (this.shutdown) {
|
||||
return;
|
||||
}
|
||||
this.shutdown = true;
|
||||
this.writer.goAway(this.lastGoodStreamId, errorCode, Util.EMPTY_BYTE_ARRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
start(true);
|
||||
}
|
||||
|
||||
synchronized void updateConnectionFlowControl(long j) {
|
||||
this.unacknowledgedBytesRead += j;
|
||||
if (this.unacknowledgedBytesRead >= this.okHttpSettings.getInitialWindowSize() / 2) {
|
||||
writeWindowUpdateLater(0, this.unacknowledgedBytesRead);
|
||||
this.unacknowledgedBytesRead = 0L;
|
||||
}
|
||||
}
|
||||
|
||||
public void writeData(int i, boolean z, Buffer buffer, long j) throws IOException {
|
||||
int min;
|
||||
long j2;
|
||||
if (j == 0) {
|
||||
this.writer.data(z, i, buffer, 0);
|
||||
return;
|
||||
}
|
||||
while (j > 0) {
|
||||
synchronized (this) {
|
||||
while (this.bytesLeftInWriteWindow <= 0) {
|
||||
try {
|
||||
if (!this.streams.containsKey(Integer.valueOf(i))) {
|
||||
throw new IOException("stream closed");
|
||||
}
|
||||
wait();
|
||||
} catch (InterruptedException unused) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new InterruptedIOException();
|
||||
}
|
||||
}
|
||||
min = Math.min((int) Math.min(j, this.bytesLeftInWriteWindow), this.writer.maxDataLength());
|
||||
j2 = min;
|
||||
this.bytesLeftInWriteWindow -= j2;
|
||||
}
|
||||
j -= j2;
|
||||
this.writer.data(z && j == 0, i, buffer, min);
|
||||
}
|
||||
}
|
||||
|
||||
void writePing(boolean z, int i, int i2) {
|
||||
boolean z2;
|
||||
if (!z) {
|
||||
synchronized (this) {
|
||||
z2 = this.awaitingPong;
|
||||
this.awaitingPong = true;
|
||||
}
|
||||
if (z2) {
|
||||
failConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.writer.ping(z, i, i2);
|
||||
} catch (IOException unused) {
|
||||
failConnection();
|
||||
}
|
||||
}
|
||||
|
||||
void writePingAndAwaitPong() throws InterruptedException {
|
||||
writePing(false, 1330343787, -257978967);
|
||||
awaitPong();
|
||||
}
|
||||
|
||||
void writeSynReply(int i, boolean z, List<Header> list) throws IOException {
|
||||
this.writer.synReply(z, i, list);
|
||||
}
|
||||
|
||||
void writeSynReset(int i, ErrorCode errorCode) throws IOException {
|
||||
this.writer.rstStream(i, errorCode);
|
||||
}
|
||||
|
||||
void writeSynResetLater(final int i, final ErrorCode errorCode) {
|
||||
try {
|
||||
this.writerExecutor.execute(new NamedRunnable("OkHttp %s stream %d", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.1
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
try {
|
||||
Http2Connection.this.writeSynReset(i, errorCode);
|
||||
} catch (IOException unused) {
|
||||
Http2Connection.this.failConnection();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
}
|
||||
|
||||
void writeWindowUpdateLater(final int i, final long j) {
|
||||
try {
|
||||
this.writerExecutor.execute(new NamedRunnable("OkHttp Window Update %s stream %d", new Object[]{this.hostname, Integer.valueOf(i)}) { // from class: okhttp3.internal.http2.Http2Connection.2
|
||||
@Override // okhttp3.internal.NamedRunnable
|
||||
public void execute() {
|
||||
try {
|
||||
Http2Connection.this.writer.windowUpdate(i, j);
|
||||
} catch (IOException unused) {
|
||||
Http2Connection.this.failConnection();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException unused) {
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX WARN: Removed duplicated region for block: B:21:0x0043 A[Catch: all -> 0x0075, TryCatch #0 {, blocks: (B:6:0x0007, B:8:0x000e, B:9:0x0013, B:11:0x0017, B:13:0x002b, B:15:0x0033, B:19:0x003d, B:21:0x0043, B:22:0x004c, B:36:0x006f, B:37:0x0074), top: B:5:0x0007, outer: #1 }] */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
private okhttp3.internal.http2.Http2Stream newStream(int r11, java.util.List<okhttp3.internal.http2.Header> r12, boolean r13) throws java.io.IOException {
|
||||
/*
|
||||
r10 = this;
|
||||
r6 = r13 ^ 1
|
||||
r4 = 0
|
||||
okhttp3.internal.http2.Http2Writer r7 = r10.writer
|
||||
monitor-enter(r7)
|
||||
monitor-enter(r10) // Catch: java.lang.Throwable -> L78
|
||||
int r0 = r10.nextStreamId // Catch: java.lang.Throwable -> L75
|
||||
r1 = 1073741823(0x3fffffff, float:1.9999999)
|
||||
if (r0 <= r1) goto L13
|
||||
okhttp3.internal.http2.ErrorCode r0 = okhttp3.internal.http2.ErrorCode.REFUSED_STREAM // Catch: java.lang.Throwable -> L75
|
||||
r10.shutdown(r0) // Catch: java.lang.Throwable -> L75
|
||||
L13:
|
||||
boolean r0 = r10.shutdown // Catch: java.lang.Throwable -> L75
|
||||
if (r0 != 0) goto L6f
|
||||
int r8 = r10.nextStreamId // Catch: java.lang.Throwable -> L75
|
||||
int r0 = r10.nextStreamId // Catch: java.lang.Throwable -> L75
|
||||
int r0 = r0 + 2
|
||||
r10.nextStreamId = r0 // Catch: java.lang.Throwable -> L75
|
||||
okhttp3.internal.http2.Http2Stream r9 = new okhttp3.internal.http2.Http2Stream // Catch: java.lang.Throwable -> L75
|
||||
r0 = r9
|
||||
r1 = r8
|
||||
r2 = r10
|
||||
r3 = r6
|
||||
r5 = r12
|
||||
r0.<init>(r1, r2, r3, r4, r5) // Catch: java.lang.Throwable -> L75
|
||||
if (r13 == 0) goto L3c
|
||||
long r0 = r10.bytesLeftInWriteWindow // Catch: java.lang.Throwable -> L75
|
||||
r2 = 0
|
||||
int r13 = (r0 > r2 ? 1 : (r0 == r2 ? 0 : -1))
|
||||
if (r13 == 0) goto L3c
|
||||
long r0 = r9.bytesLeftInWriteWindow // Catch: java.lang.Throwable -> L75
|
||||
int r13 = (r0 > r2 ? 1 : (r0 == r2 ? 0 : -1))
|
||||
if (r13 != 0) goto L3a
|
||||
goto L3c
|
||||
L3a:
|
||||
r13 = 0
|
||||
goto L3d
|
||||
L3c:
|
||||
r13 = 1
|
||||
L3d:
|
||||
boolean r0 = r9.isOpen() // Catch: java.lang.Throwable -> L75
|
||||
if (r0 == 0) goto L4c
|
||||
java.util.Map<java.lang.Integer, okhttp3.internal.http2.Http2Stream> r0 = r10.streams // Catch: java.lang.Throwable -> L75
|
||||
java.lang.Integer r1 = java.lang.Integer.valueOf(r8) // Catch: java.lang.Throwable -> L75
|
||||
r0.put(r1, r9) // Catch: java.lang.Throwable -> L75
|
||||
L4c:
|
||||
monitor-exit(r10) // Catch: java.lang.Throwable -> L75
|
||||
if (r11 != 0) goto L55
|
||||
okhttp3.internal.http2.Http2Writer r0 = r10.writer // Catch: java.lang.Throwable -> L78
|
||||
r0.synStream(r6, r8, r11, r12) // Catch: java.lang.Throwable -> L78
|
||||
goto L5e
|
||||
L55:
|
||||
boolean r0 = r10.client // Catch: java.lang.Throwable -> L78
|
||||
if (r0 != 0) goto L67
|
||||
okhttp3.internal.http2.Http2Writer r0 = r10.writer // Catch: java.lang.Throwable -> L78
|
||||
r0.pushPromise(r11, r8, r12) // Catch: java.lang.Throwable -> L78
|
||||
L5e:
|
||||
monitor-exit(r7) // Catch: java.lang.Throwable -> L78
|
||||
if (r13 == 0) goto L66
|
||||
okhttp3.internal.http2.Http2Writer r11 = r10.writer
|
||||
r11.flush()
|
||||
L66:
|
||||
return r9
|
||||
L67:
|
||||
java.lang.IllegalArgumentException r11 = new java.lang.IllegalArgumentException // Catch: java.lang.Throwable -> L78
|
||||
java.lang.String r12 = "client streams shouldn't have associated stream IDs"
|
||||
r11.<init>(r12) // Catch: java.lang.Throwable -> L78
|
||||
throw r11 // Catch: java.lang.Throwable -> L78
|
||||
L6f:
|
||||
okhttp3.internal.http2.ConnectionShutdownException r11 = new okhttp3.internal.http2.ConnectionShutdownException // Catch: java.lang.Throwable -> L75
|
||||
r11.<init>() // Catch: java.lang.Throwable -> L75
|
||||
throw r11 // Catch: java.lang.Throwable -> L75
|
||||
L75:
|
||||
r11 = move-exception
|
||||
monitor-exit(r10) // Catch: java.lang.Throwable -> L75
|
||||
throw r11 // Catch: java.lang.Throwable -> L78
|
||||
L78:
|
||||
r11 = move-exception
|
||||
monitor-exit(r7) // Catch: java.lang.Throwable -> L78
|
||||
throw r11
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.http2.Http2Connection.newStream(int, java.util.List, boolean):okhttp3.internal.http2.Http2Stream");
|
||||
}
|
||||
|
||||
void close(ErrorCode errorCode, ErrorCode errorCode2) throws IOException {
|
||||
Http2Stream[] http2StreamArr = null;
|
||||
try {
|
||||
shutdown(errorCode);
|
||||
e = null;
|
||||
} catch (IOException e) {
|
||||
e = e;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (!this.streams.isEmpty()) {
|
||||
http2StreamArr = (Http2Stream[]) this.streams.values().toArray(new Http2Stream[this.streams.size()]);
|
||||
this.streams.clear();
|
||||
}
|
||||
}
|
||||
if (http2StreamArr != null) {
|
||||
for (Http2Stream http2Stream : http2StreamArr) {
|
||||
try {
|
||||
http2Stream.close(errorCode2);
|
||||
} catch (IOException e2) {
|
||||
if (e != null) {
|
||||
e = e2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.writer.close();
|
||||
} catch (IOException e3) {
|
||||
if (e == null) {
|
||||
e = e3;
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.socket.close();
|
||||
} catch (IOException e4) {
|
||||
e = e4;
|
||||
}
|
||||
this.writerExecutor.shutdown();
|
||||
this.pushExecutor.shutdown();
|
||||
if (e != null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
void start(boolean z) throws IOException {
|
||||
if (z) {
|
||||
this.writer.connectionPreface();
|
||||
this.writer.settings(this.okHttpSettings);
|
||||
if (this.okHttpSettings.getInitialWindowSize() != 65535) {
|
||||
this.writer.windowUpdate(0, r6 - 65535);
|
||||
}
|
||||
}
|
||||
new Thread(this.readerRunnable).start();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
boolean client;
|
||||
String hostname;
|
||||
int pingIntervalMillis;
|
||||
BufferedSink sink;
|
||||
Socket socket;
|
||||
BufferedSource source;
|
||||
Listener listener = Listener.REFUSE_INCOMING_STREAMS;
|
||||
PushObserver pushObserver = PushObserver.CANCEL;
|
||||
|
||||
public Builder(boolean z) {
|
||||
this.client = z;
|
||||
}
|
||||
|
||||
public Http2Connection build() {
|
||||
return new Http2Connection(this);
|
||||
}
|
||||
|
||||
public Builder listener(Listener listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder pingIntervalMillis(int i) {
|
||||
this.pingIntervalMillis = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder pushObserver(PushObserver pushObserver) {
|
||||
this.pushObserver = pushObserver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder socket(Socket socket) throws IOException {
|
||||
return socket(socket, ((InetSocketAddress) socket.getRemoteSocketAddress()).getHostName(), Okio.buffer(Okio.source(socket)), Okio.buffer(Okio.sink(socket)));
|
||||
}
|
||||
|
||||
public Builder socket(Socket socket, String str, BufferedSource bufferedSource, BufferedSink bufferedSink) {
|
||||
this.socket = socket;
|
||||
this.hostname = str;
|
||||
this.source = bufferedSource;
|
||||
this.sink = bufferedSink;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
367
sources/okhttp3/internal/http2/Http2Reader.java
Normal file
367
sources/okhttp3/internal/http2/Http2Reader.java
Normal file
@@ -0,0 +1,367 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import com.ubt.jimu.base.util.FileUtil;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.http2.Hpack;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class Http2Reader implements Closeable {
|
||||
static final Logger logger = Logger.getLogger(Http2.class.getName());
|
||||
private final boolean client;
|
||||
private final ContinuationSource continuation;
|
||||
final Hpack.Reader hpackReader;
|
||||
private final BufferedSource source;
|
||||
|
||||
static final class ContinuationSource implements Source {
|
||||
byte flags;
|
||||
int left;
|
||||
int length;
|
||||
short padding;
|
||||
private final BufferedSource source;
|
||||
int streamId;
|
||||
|
||||
ContinuationSource(BufferedSource bufferedSource) {
|
||||
this.source = bufferedSource;
|
||||
}
|
||||
|
||||
private void readContinuationHeader() throws IOException {
|
||||
int i = this.streamId;
|
||||
int readMedium = Http2Reader.readMedium(this.source);
|
||||
this.left = readMedium;
|
||||
this.length = readMedium;
|
||||
byte readByte = (byte) (this.source.readByte() & 255);
|
||||
this.flags = (byte) (this.source.readByte() & 255);
|
||||
if (Http2Reader.logger.isLoggable(Level.FINE)) {
|
||||
Http2Reader.logger.fine(Http2.frameLog(true, this.streamId, this.length, readByte, this.flags));
|
||||
}
|
||||
this.streamId = this.source.readInt() & Integer.MAX_VALUE;
|
||||
if (readByte != 9) {
|
||||
throw Http2.ioException("%s != TYPE_CONTINUATION", Byte.valueOf(readByte));
|
||||
}
|
||||
if (this.streamId != i) {
|
||||
throw Http2.ioException("TYPE_CONTINUATION streamId changed", new Object[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
while (true) {
|
||||
int i = this.left;
|
||||
if (i != 0) {
|
||||
long read = this.source.read(buffer, Math.min(j, i));
|
||||
if (read == -1) {
|
||||
return -1L;
|
||||
}
|
||||
this.left = (int) (this.left - read);
|
||||
return read;
|
||||
}
|
||||
this.source.skip(this.padding);
|
||||
this.padding = (short) 0;
|
||||
if ((this.flags & 4) != 0) {
|
||||
return -1L;
|
||||
}
|
||||
readContinuationHeader();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return this.source.timeout();
|
||||
}
|
||||
}
|
||||
|
||||
interface Handler {
|
||||
void ackSettings();
|
||||
|
||||
void alternateService(int i, String str, ByteString byteString, String str2, int i2, long j);
|
||||
|
||||
void data(boolean z, int i, BufferedSource bufferedSource, int i2) throws IOException;
|
||||
|
||||
void goAway(int i, ErrorCode errorCode, ByteString byteString);
|
||||
|
||||
void headers(boolean z, int i, int i2, List<Header> list);
|
||||
|
||||
void ping(boolean z, int i, int i2);
|
||||
|
||||
void priority(int i, int i2, int i3, boolean z);
|
||||
|
||||
void pushPromise(int i, int i2, List<Header> list) throws IOException;
|
||||
|
||||
void rstStream(int i, ErrorCode errorCode);
|
||||
|
||||
void settings(boolean z, Settings settings);
|
||||
|
||||
void windowUpdate(int i, long j);
|
||||
}
|
||||
|
||||
Http2Reader(BufferedSource bufferedSource, boolean z) {
|
||||
this.source = bufferedSource;
|
||||
this.client = z;
|
||||
this.continuation = new ContinuationSource(this.source);
|
||||
this.hpackReader = new Hpack.Reader(FileUtil.ZIP_BUFFER_SIZE, this.continuation);
|
||||
}
|
||||
|
||||
static int lengthWithoutPadding(int i, byte b, short s) throws IOException {
|
||||
if ((b & 8) != 0) {
|
||||
i--;
|
||||
}
|
||||
if (s <= i) {
|
||||
return (short) (i - s);
|
||||
}
|
||||
throw Http2.ioException("PROTOCOL_ERROR padding %s > remaining length %s", Short.valueOf(s), Integer.valueOf(i));
|
||||
}
|
||||
|
||||
private void readData(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i2 == 0) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR: TYPE_DATA streamId == 0", new Object[0]);
|
||||
}
|
||||
boolean z = (b & 1) != 0;
|
||||
if ((b & 32) != 0) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR: FLAG_COMPRESSED without SETTINGS_COMPRESS_DATA", new Object[0]);
|
||||
}
|
||||
short readByte = (b & 8) != 0 ? (short) (this.source.readByte() & 255) : (short) 0;
|
||||
handler.data(z, i2, this.source, lengthWithoutPadding(i, b, readByte));
|
||||
this.source.skip(readByte);
|
||||
}
|
||||
|
||||
private void readGoAway(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i < 8) {
|
||||
throw Http2.ioException("TYPE_GOAWAY length < 8: %s", Integer.valueOf(i));
|
||||
}
|
||||
if (i2 != 0) {
|
||||
throw Http2.ioException("TYPE_GOAWAY streamId != 0", new Object[0]);
|
||||
}
|
||||
int readInt = this.source.readInt();
|
||||
int readInt2 = this.source.readInt();
|
||||
int i3 = i - 8;
|
||||
ErrorCode fromHttp2 = ErrorCode.fromHttp2(readInt2);
|
||||
if (fromHttp2 == null) {
|
||||
throw Http2.ioException("TYPE_GOAWAY unexpected error code: %d", Integer.valueOf(readInt2));
|
||||
}
|
||||
ByteString byteString = ByteString.EMPTY;
|
||||
if (i3 > 0) {
|
||||
byteString = this.source.readByteString(i3);
|
||||
}
|
||||
handler.goAway(readInt, fromHttp2, byteString);
|
||||
}
|
||||
|
||||
private List<Header> readHeaderBlock(int i, short s, byte b, int i2) throws IOException {
|
||||
ContinuationSource continuationSource = this.continuation;
|
||||
continuationSource.left = i;
|
||||
continuationSource.length = i;
|
||||
continuationSource.padding = s;
|
||||
continuationSource.flags = b;
|
||||
continuationSource.streamId = i2;
|
||||
this.hpackReader.readHeaders();
|
||||
return this.hpackReader.getAndResetHeaderList();
|
||||
}
|
||||
|
||||
private void readHeaders(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i2 == 0) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR: TYPE_HEADERS streamId == 0", new Object[0]);
|
||||
}
|
||||
boolean z = (b & 1) != 0;
|
||||
short readByte = (b & 8) != 0 ? (short) (this.source.readByte() & 255) : (short) 0;
|
||||
if ((b & 32) != 0) {
|
||||
readPriority(handler, i2);
|
||||
i -= 5;
|
||||
}
|
||||
handler.headers(z, i2, -1, readHeaderBlock(lengthWithoutPadding(i, b, readByte), readByte, b, i2));
|
||||
}
|
||||
|
||||
static int readMedium(BufferedSource bufferedSource) throws IOException {
|
||||
return (bufferedSource.readByte() & 255) | ((bufferedSource.readByte() & 255) << 16) | ((bufferedSource.readByte() & 255) << 8);
|
||||
}
|
||||
|
||||
private void readPing(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i != 8) {
|
||||
throw Http2.ioException("TYPE_PING length != 8: %s", Integer.valueOf(i));
|
||||
}
|
||||
if (i2 != 0) {
|
||||
throw Http2.ioException("TYPE_PING streamId != 0", new Object[0]);
|
||||
}
|
||||
handler.ping((b & 1) != 0, this.source.readInt(), this.source.readInt());
|
||||
}
|
||||
|
||||
private void readPriority(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i != 5) {
|
||||
throw Http2.ioException("TYPE_PRIORITY length: %d != 5", Integer.valueOf(i));
|
||||
}
|
||||
if (i2 == 0) {
|
||||
throw Http2.ioException("TYPE_PRIORITY streamId == 0", new Object[0]);
|
||||
}
|
||||
readPriority(handler, i2);
|
||||
}
|
||||
|
||||
private void readPushPromise(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i2 == 0) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR: TYPE_PUSH_PROMISE streamId == 0", new Object[0]);
|
||||
}
|
||||
short readByte = (b & 8) != 0 ? (short) (this.source.readByte() & 255) : (short) 0;
|
||||
handler.pushPromise(i2, this.source.readInt() & Integer.MAX_VALUE, readHeaderBlock(lengthWithoutPadding(i - 4, b, readByte), readByte, b, i2));
|
||||
}
|
||||
|
||||
private void readRstStream(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i != 4) {
|
||||
throw Http2.ioException("TYPE_RST_STREAM length: %d != 4", Integer.valueOf(i));
|
||||
}
|
||||
if (i2 == 0) {
|
||||
throw Http2.ioException("TYPE_RST_STREAM streamId == 0", new Object[0]);
|
||||
}
|
||||
int readInt = this.source.readInt();
|
||||
ErrorCode fromHttp2 = ErrorCode.fromHttp2(readInt);
|
||||
if (fromHttp2 == null) {
|
||||
throw Http2.ioException("TYPE_RST_STREAM unexpected error code: %d", Integer.valueOf(readInt));
|
||||
}
|
||||
handler.rstStream(i2, fromHttp2);
|
||||
}
|
||||
|
||||
private void readSettings(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i2 != 0) {
|
||||
throw Http2.ioException("TYPE_SETTINGS streamId != 0", new Object[0]);
|
||||
}
|
||||
if ((b & 1) != 0) {
|
||||
if (i != 0) {
|
||||
throw Http2.ioException("FRAME_SIZE_ERROR ack frame should be empty!", new Object[0]);
|
||||
}
|
||||
handler.ackSettings();
|
||||
return;
|
||||
}
|
||||
if (i % 6 != 0) {
|
||||
throw Http2.ioException("TYPE_SETTINGS length %% 6 != 0: %s", Integer.valueOf(i));
|
||||
}
|
||||
Settings settings = new Settings();
|
||||
for (int i3 = 0; i3 < i; i3 += 6) {
|
||||
int readShort = this.source.readShort() & 65535;
|
||||
int readInt = this.source.readInt();
|
||||
switch (readShort) {
|
||||
case 2:
|
||||
if (readInt != 0 && readInt != 1) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR SETTINGS_ENABLE_PUSH != 0 or 1", new Object[0]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
readShort = 4;
|
||||
break;
|
||||
case 4:
|
||||
readShort = 7;
|
||||
if (readInt < 0) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR SETTINGS_INITIAL_WINDOW_SIZE > 2^31 - 1", new Object[0]);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (readInt < 16384 || readInt > 16777215) {
|
||||
throw Http2.ioException("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: %s", Integer.valueOf(readInt));
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
settings.set(readShort, readInt);
|
||||
}
|
||||
handler.settings(false, settings);
|
||||
}
|
||||
|
||||
private void readWindowUpdate(Handler handler, int i, byte b, int i2) throws IOException {
|
||||
if (i != 4) {
|
||||
throw Http2.ioException("TYPE_WINDOW_UPDATE length !=4: %s", Integer.valueOf(i));
|
||||
}
|
||||
long readInt = this.source.readInt() & 2147483647L;
|
||||
if (readInt == 0) {
|
||||
throw Http2.ioException("windowSizeIncrement was 0", Long.valueOf(readInt));
|
||||
}
|
||||
handler.windowUpdate(i2, readInt);
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
this.source.close();
|
||||
}
|
||||
|
||||
public boolean nextFrame(boolean z, Handler handler) throws IOException {
|
||||
try {
|
||||
this.source.require(9L);
|
||||
int readMedium = readMedium(this.source);
|
||||
if (readMedium < 0 || readMedium > 16384) {
|
||||
throw Http2.ioException("FRAME_SIZE_ERROR: %s", Integer.valueOf(readMedium));
|
||||
}
|
||||
byte readByte = (byte) (this.source.readByte() & 255);
|
||||
if (z && readByte != 4) {
|
||||
throw Http2.ioException("Expected a SETTINGS frame but was %s", Byte.valueOf(readByte));
|
||||
}
|
||||
byte readByte2 = (byte) (this.source.readByte() & 255);
|
||||
int readInt = this.source.readInt() & Integer.MAX_VALUE;
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.fine(Http2.frameLog(true, readInt, readMedium, readByte, readByte2));
|
||||
}
|
||||
switch (readByte) {
|
||||
case 0:
|
||||
readData(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 1:
|
||||
readHeaders(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 2:
|
||||
readPriority(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 3:
|
||||
readRstStream(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 4:
|
||||
readSettings(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 5:
|
||||
readPushPromise(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 6:
|
||||
readPing(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 7:
|
||||
readGoAway(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
case 8:
|
||||
readWindowUpdate(handler, readMedium, readByte2, readInt);
|
||||
return true;
|
||||
default:
|
||||
this.source.skip(readMedium);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void readConnectionPreface(Handler handler) throws IOException {
|
||||
if (this.client) {
|
||||
if (!nextFrame(true, handler)) {
|
||||
throw Http2.ioException("Required SETTINGS preface not received", new Object[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ByteString readByteString = this.source.readByteString(Http2.CONNECTION_PREFACE.size());
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.fine(Util.format("<< CONNECTION %s", readByteString.hex()));
|
||||
}
|
||||
if (!Http2.CONNECTION_PREFACE.equals(readByteString)) {
|
||||
throw Http2.ioException("Expected a connection header but was %s", readByteString.utf8());
|
||||
}
|
||||
}
|
||||
|
||||
private void readPriority(Handler handler, int i) throws IOException {
|
||||
int readInt = this.source.readInt();
|
||||
handler.priority(i, readInt & Integer.MAX_VALUE, (this.source.readByte() & 255) + 1, (Integer.MIN_VALUE & readInt) != 0);
|
||||
}
|
||||
}
|
||||
497
sources/okhttp3/internal/http2/Http2Stream.java
Normal file
497
sources/okhttp3/internal/http2/Http2Stream.java
Normal file
@@ -0,0 +1,497 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import okio.AsyncTimeout;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Http2Stream {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
long bytesLeftInWriteWindow;
|
||||
final Http2Connection connection;
|
||||
private boolean hasResponseHeaders;
|
||||
final int id;
|
||||
private final List<Header> requestHeaders;
|
||||
private List<Header> responseHeaders;
|
||||
final FramingSink sink;
|
||||
private final FramingSource source;
|
||||
long unacknowledgedBytesRead = 0;
|
||||
final StreamTimeout readTimeout = new StreamTimeout();
|
||||
final StreamTimeout writeTimeout = new StreamTimeout();
|
||||
ErrorCode errorCode = null;
|
||||
|
||||
final class FramingSink implements Sink {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
private static final long EMIT_BUFFER_SIZE = 16384;
|
||||
boolean closed;
|
||||
boolean finished;
|
||||
private final Buffer sendBuffer = new Buffer();
|
||||
|
||||
FramingSink() {
|
||||
}
|
||||
|
||||
private void emitFrame(boolean z) throws IOException {
|
||||
long min;
|
||||
synchronized (Http2Stream.this) {
|
||||
Http2Stream.this.writeTimeout.enter();
|
||||
while (Http2Stream.this.bytesLeftInWriteWindow <= 0 && !this.finished && !this.closed && Http2Stream.this.errorCode == null) {
|
||||
try {
|
||||
Http2Stream.this.waitForIo();
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
Http2Stream.this.writeTimeout.exitAndThrowIfTimedOut();
|
||||
Http2Stream.this.checkOutNotClosed();
|
||||
min = Math.min(Http2Stream.this.bytesLeftInWriteWindow, this.sendBuffer.size());
|
||||
Http2Stream.this.bytesLeftInWriteWindow -= min;
|
||||
}
|
||||
Http2Stream.this.writeTimeout.enter();
|
||||
try {
|
||||
Http2Stream.this.connection.writeData(Http2Stream.this.id, z && min == this.sendBuffer.size(), this.sendBuffer, min);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
synchronized (Http2Stream.this) {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
if (!Http2Stream.this.sink.finished) {
|
||||
if (this.sendBuffer.size() > 0) {
|
||||
while (this.sendBuffer.size() > 0) {
|
||||
emitFrame(true);
|
||||
}
|
||||
} else {
|
||||
Http2Stream http2Stream = Http2Stream.this;
|
||||
http2Stream.connection.writeData(http2Stream.id, true, null, 0L);
|
||||
}
|
||||
}
|
||||
synchronized (Http2Stream.this) {
|
||||
this.closed = true;
|
||||
}
|
||||
Http2Stream.this.connection.flush();
|
||||
Http2Stream.this.cancelStreamIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Flushable
|
||||
public void flush() throws IOException {
|
||||
synchronized (Http2Stream.this) {
|
||||
Http2Stream.this.checkOutNotClosed();
|
||||
}
|
||||
while (this.sendBuffer.size() > 0) {
|
||||
emitFrame(false);
|
||||
Http2Stream.this.connection.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public Timeout timeout() {
|
||||
return Http2Stream.this.writeTimeout;
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
this.sendBuffer.write(buffer, j);
|
||||
while (this.sendBuffer.size() >= 16384) {
|
||||
emitFrame(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class FramingSource implements Source {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
boolean closed;
|
||||
boolean finished;
|
||||
private final long maxByteCount;
|
||||
private final Buffer receiveBuffer = new Buffer();
|
||||
private final Buffer readBuffer = new Buffer();
|
||||
|
||||
FramingSource(long j) {
|
||||
this.maxByteCount = j;
|
||||
}
|
||||
|
||||
private void updateConnectionFlowControl(long j) {
|
||||
Http2Stream.this.connection.updateConnectionFlowControl(j);
|
||||
}
|
||||
|
||||
private void waitUntilReadable() throws IOException {
|
||||
Http2Stream.this.readTimeout.enter();
|
||||
while (this.readBuffer.size() == 0 && !this.finished && !this.closed && Http2Stream.this.errorCode == null) {
|
||||
try {
|
||||
Http2Stream.this.waitForIo();
|
||||
} finally {
|
||||
Http2Stream.this.readTimeout.exitAndThrowIfTimedOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
long size;
|
||||
synchronized (Http2Stream.this) {
|
||||
this.closed = true;
|
||||
size = this.readBuffer.size();
|
||||
this.readBuffer.clear();
|
||||
Http2Stream.this.notifyAll();
|
||||
}
|
||||
if (size > 0) {
|
||||
updateConnectionFlowControl(size);
|
||||
}
|
||||
Http2Stream.this.cancelStreamIfNecessary();
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public long read(Buffer buffer, long j) throws IOException {
|
||||
ErrorCode errorCode;
|
||||
long j2;
|
||||
if (j < 0) {
|
||||
throw new IllegalArgumentException("byteCount < 0: " + j);
|
||||
}
|
||||
synchronized (Http2Stream.this) {
|
||||
waitUntilReadable();
|
||||
if (this.closed) {
|
||||
throw new IOException("stream closed");
|
||||
}
|
||||
errorCode = Http2Stream.this.errorCode;
|
||||
if (this.readBuffer.size() > 0) {
|
||||
j2 = this.readBuffer.read(buffer, Math.min(j, this.readBuffer.size()));
|
||||
Http2Stream.this.unacknowledgedBytesRead += j2;
|
||||
} else {
|
||||
j2 = -1;
|
||||
}
|
||||
if (errorCode == null && Http2Stream.this.unacknowledgedBytesRead >= Http2Stream.this.connection.okHttpSettings.getInitialWindowSize() / 2) {
|
||||
Http2Stream.this.connection.writeWindowUpdateLater(Http2Stream.this.id, Http2Stream.this.unacknowledgedBytesRead);
|
||||
Http2Stream.this.unacknowledgedBytesRead = 0L;
|
||||
}
|
||||
}
|
||||
if (j2 != -1) {
|
||||
updateConnectionFlowControl(j2);
|
||||
return j2;
|
||||
}
|
||||
if (errorCode == null) {
|
||||
return -1L;
|
||||
}
|
||||
throw new StreamResetException(errorCode);
|
||||
}
|
||||
|
||||
void receive(BufferedSource bufferedSource, long j) throws IOException {
|
||||
boolean z;
|
||||
boolean z2;
|
||||
boolean z3;
|
||||
while (j > 0) {
|
||||
synchronized (Http2Stream.this) {
|
||||
z = this.finished;
|
||||
z2 = true;
|
||||
z3 = this.readBuffer.size() + j > this.maxByteCount;
|
||||
}
|
||||
if (z3) {
|
||||
bufferedSource.skip(j);
|
||||
Http2Stream.this.closeLater(ErrorCode.FLOW_CONTROL_ERROR);
|
||||
return;
|
||||
}
|
||||
if (z) {
|
||||
bufferedSource.skip(j);
|
||||
return;
|
||||
}
|
||||
long read = bufferedSource.read(this.receiveBuffer, j);
|
||||
if (read == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
j -= read;
|
||||
synchronized (Http2Stream.this) {
|
||||
if (this.readBuffer.size() != 0) {
|
||||
z2 = false;
|
||||
}
|
||||
this.readBuffer.writeAll(this.receiveBuffer);
|
||||
if (z2) {
|
||||
Http2Stream.this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return Http2Stream.this.readTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
class StreamTimeout extends AsyncTimeout {
|
||||
StreamTimeout() {
|
||||
}
|
||||
|
||||
public void exitAndThrowIfTimedOut() throws IOException {
|
||||
if (exit()) {
|
||||
throw newTimeoutException(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.AsyncTimeout
|
||||
protected IOException newTimeoutException(IOException iOException) {
|
||||
SocketTimeoutException socketTimeoutException = new SocketTimeoutException("timeout");
|
||||
if (iOException != null) {
|
||||
socketTimeoutException.initCause(iOException);
|
||||
}
|
||||
return socketTimeoutException;
|
||||
}
|
||||
|
||||
@Override // okio.AsyncTimeout
|
||||
protected void timedOut() {
|
||||
Http2Stream.this.closeLater(ErrorCode.CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
Http2Stream(int i, Http2Connection http2Connection, boolean z, boolean z2, List<Header> list) {
|
||||
if (http2Connection == null) {
|
||||
throw new NullPointerException("connection == null");
|
||||
}
|
||||
if (list == null) {
|
||||
throw new NullPointerException("requestHeaders == null");
|
||||
}
|
||||
this.id = i;
|
||||
this.connection = http2Connection;
|
||||
this.bytesLeftInWriteWindow = http2Connection.peerSettings.getInitialWindowSize();
|
||||
this.source = new FramingSource(http2Connection.okHttpSettings.getInitialWindowSize());
|
||||
this.sink = new FramingSink();
|
||||
this.source.finished = z2;
|
||||
this.sink.finished = z;
|
||||
this.requestHeaders = list;
|
||||
}
|
||||
|
||||
private boolean closeInternal(ErrorCode errorCode) {
|
||||
synchronized (this) {
|
||||
if (this.errorCode != null) {
|
||||
return false;
|
||||
}
|
||||
if (this.source.finished && this.sink.finished) {
|
||||
return false;
|
||||
}
|
||||
this.errorCode = errorCode;
|
||||
notifyAll();
|
||||
this.connection.removeStream(this.id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void addBytesToWriteWindow(long j) {
|
||||
this.bytesLeftInWriteWindow += j;
|
||||
if (j > 0) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
void cancelStreamIfNecessary() throws IOException {
|
||||
boolean z;
|
||||
boolean isOpen;
|
||||
synchronized (this) {
|
||||
z = !this.source.finished && this.source.closed && (this.sink.finished || this.sink.closed);
|
||||
isOpen = isOpen();
|
||||
}
|
||||
if (z) {
|
||||
close(ErrorCode.CANCEL);
|
||||
} else {
|
||||
if (isOpen) {
|
||||
return;
|
||||
}
|
||||
this.connection.removeStream(this.id);
|
||||
}
|
||||
}
|
||||
|
||||
void checkOutNotClosed() throws IOException {
|
||||
FramingSink framingSink = this.sink;
|
||||
if (framingSink.closed) {
|
||||
throw new IOException("stream closed");
|
||||
}
|
||||
if (framingSink.finished) {
|
||||
throw new IOException("stream finished");
|
||||
}
|
||||
ErrorCode errorCode = this.errorCode;
|
||||
if (errorCode != null) {
|
||||
throw new StreamResetException(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void close(ErrorCode errorCode) throws IOException {
|
||||
if (closeInternal(errorCode)) {
|
||||
this.connection.writeSynReset(this.id, errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeLater(ErrorCode errorCode) {
|
||||
if (closeInternal(errorCode)) {
|
||||
this.connection.writeSynResetLater(this.id, errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public Http2Connection getConnection() {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
public synchronized ErrorCode getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public List<Header> getRequestHeaders() {
|
||||
return this.requestHeaders;
|
||||
}
|
||||
|
||||
public Sink getSink() {
|
||||
synchronized (this) {
|
||||
if (!this.hasResponseHeaders && !isLocallyInitiated()) {
|
||||
throw new IllegalStateException("reply before requesting the sink");
|
||||
}
|
||||
}
|
||||
return this.sink;
|
||||
}
|
||||
|
||||
public Source getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public boolean isLocallyInitiated() {
|
||||
return this.connection.client == ((this.id & 1) == 1);
|
||||
}
|
||||
|
||||
public synchronized boolean isOpen() {
|
||||
if (this.errorCode != null) {
|
||||
return false;
|
||||
}
|
||||
if ((this.source.finished || this.source.closed) && (this.sink.finished || this.sink.closed)) {
|
||||
if (this.hasResponseHeaders) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Timeout readTimeout() {
|
||||
return this.readTimeout;
|
||||
}
|
||||
|
||||
void receiveData(BufferedSource bufferedSource, int i) throws IOException {
|
||||
this.source.receive(bufferedSource, i);
|
||||
}
|
||||
|
||||
void receiveFin() {
|
||||
boolean isOpen;
|
||||
synchronized (this) {
|
||||
this.source.finished = true;
|
||||
isOpen = isOpen();
|
||||
notifyAll();
|
||||
}
|
||||
if (isOpen) {
|
||||
return;
|
||||
}
|
||||
this.connection.removeStream(this.id);
|
||||
}
|
||||
|
||||
void receiveHeaders(List<Header> list) {
|
||||
boolean z;
|
||||
synchronized (this) {
|
||||
z = true;
|
||||
this.hasResponseHeaders = true;
|
||||
if (this.responseHeaders == null) {
|
||||
this.responseHeaders = list;
|
||||
z = isOpen();
|
||||
notifyAll();
|
||||
} else {
|
||||
ArrayList arrayList = new ArrayList();
|
||||
arrayList.addAll(this.responseHeaders);
|
||||
arrayList.add(null);
|
||||
arrayList.addAll(list);
|
||||
this.responseHeaders = arrayList;
|
||||
}
|
||||
}
|
||||
if (z) {
|
||||
return;
|
||||
}
|
||||
this.connection.removeStream(this.id);
|
||||
}
|
||||
|
||||
synchronized void receiveRstStream(ErrorCode errorCode) {
|
||||
if (this.errorCode == null) {
|
||||
this.errorCode = errorCode;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendResponseHeaders(List<Header> list, boolean z) throws IOException {
|
||||
boolean z2;
|
||||
boolean z3;
|
||||
if (list == null) {
|
||||
throw new NullPointerException("responseHeaders == null");
|
||||
}
|
||||
synchronized (this) {
|
||||
this.hasResponseHeaders = true;
|
||||
if (z) {
|
||||
z2 = false;
|
||||
z3 = false;
|
||||
} else {
|
||||
this.sink.finished = true;
|
||||
z2 = true;
|
||||
z3 = true;
|
||||
}
|
||||
}
|
||||
if (!z2) {
|
||||
synchronized (this.connection) {
|
||||
z2 = this.connection.bytesLeftInWriteWindow == 0;
|
||||
}
|
||||
}
|
||||
this.connection.writeSynReply(this.id, z3, list);
|
||||
if (z2) {
|
||||
this.connection.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized List<Header> takeResponseHeaders() throws IOException {
|
||||
List<Header> list;
|
||||
if (!isLocallyInitiated()) {
|
||||
throw new IllegalStateException("servers cannot read response headers");
|
||||
}
|
||||
this.readTimeout.enter();
|
||||
while (this.responseHeaders == null && this.errorCode == null) {
|
||||
try {
|
||||
waitForIo();
|
||||
} catch (Throwable th) {
|
||||
this.readTimeout.exitAndThrowIfTimedOut();
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
this.readTimeout.exitAndThrowIfTimedOut();
|
||||
list = this.responseHeaders;
|
||||
if (list == null) {
|
||||
throw new StreamResetException(this.errorCode);
|
||||
}
|
||||
this.responseHeaders = null;
|
||||
return list;
|
||||
}
|
||||
|
||||
void waitForIo() throws InterruptedIOException {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException unused) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new InterruptedIOException();
|
||||
}
|
||||
}
|
||||
|
||||
public Timeout writeTimeout() {
|
||||
return this.writeTimeout;
|
||||
}
|
||||
}
|
||||
240
sources/okhttp3/internal/http2/Http2Writer.java
Normal file
240
sources/okhttp3/internal/http2/Http2Writer.java
Normal file
@@ -0,0 +1,240 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.http2.Hpack;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class Http2Writer implements Closeable {
|
||||
private static final Logger logger = Logger.getLogger(Http2.class.getName());
|
||||
private final boolean client;
|
||||
private boolean closed;
|
||||
private final Buffer hpackBuffer = new Buffer();
|
||||
final Hpack.Writer hpackWriter = new Hpack.Writer(this.hpackBuffer);
|
||||
private int maxFrameSize = 16384;
|
||||
private final BufferedSink sink;
|
||||
|
||||
Http2Writer(BufferedSink bufferedSink, boolean z) {
|
||||
this.sink = bufferedSink;
|
||||
this.client = z;
|
||||
}
|
||||
|
||||
private void writeContinuationFrames(int i, long j) throws IOException {
|
||||
while (j > 0) {
|
||||
int min = (int) Math.min(this.maxFrameSize, j);
|
||||
long j2 = min;
|
||||
j -= j2;
|
||||
frameHeader(i, min, (byte) 9, j == 0 ? (byte) 4 : (byte) 0);
|
||||
this.sink.write(this.hpackBuffer, j2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeMedium(BufferedSink bufferedSink, int i) throws IOException {
|
||||
bufferedSink.writeByte((i >>> 16) & 255);
|
||||
bufferedSink.writeByte((i >>> 8) & 255);
|
||||
bufferedSink.writeByte(i & 255);
|
||||
}
|
||||
|
||||
public synchronized void applyAndAckSettings(Settings settings) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
this.maxFrameSize = settings.getMaxFrameSize(this.maxFrameSize);
|
||||
if (settings.getHeaderTableSize() != -1) {
|
||||
this.hpackWriter.setHeaderTableSizeSetting(settings.getHeaderTableSize());
|
||||
}
|
||||
frameHeader(0, 0, (byte) 4, (byte) 1);
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public synchronized void close() throws IOException {
|
||||
this.closed = true;
|
||||
this.sink.close();
|
||||
}
|
||||
|
||||
public synchronized void connectionPreface() throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
if (this.client) {
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.fine(Util.format(">> CONNECTION %s", Http2.CONNECTION_PREFACE.hex()));
|
||||
}
|
||||
this.sink.write(Http2.CONNECTION_PREFACE.toByteArray());
|
||||
this.sink.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void data(boolean z, int i, Buffer buffer, int i2) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
dataFrame(i, z ? (byte) 1 : (byte) 0, buffer, i2);
|
||||
}
|
||||
|
||||
void dataFrame(int i, byte b, Buffer buffer, int i2) throws IOException {
|
||||
frameHeader(i, i2, (byte) 0, b);
|
||||
if (i2 > 0) {
|
||||
this.sink.write(buffer, i2);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void flush() throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public void frameHeader(int i, int i2, byte b, byte b2) throws IOException {
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.fine(Http2.frameLog(false, i, i2, b, b2));
|
||||
}
|
||||
int i3 = this.maxFrameSize;
|
||||
if (i2 > i3) {
|
||||
throw Http2.illegalArgument("FRAME_SIZE_ERROR length > %d: %d", Integer.valueOf(i3), Integer.valueOf(i2));
|
||||
}
|
||||
if ((Integer.MIN_VALUE & i) != 0) {
|
||||
throw Http2.illegalArgument("reserved bit set: %s", Integer.valueOf(i));
|
||||
}
|
||||
writeMedium(this.sink, i2);
|
||||
this.sink.writeByte(b & 255);
|
||||
this.sink.writeByte(b2 & 255);
|
||||
this.sink.writeInt(i & Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public synchronized void goAway(int i, ErrorCode errorCode, byte[] bArr) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
if (errorCode.httpCode == -1) {
|
||||
throw Http2.illegalArgument("errorCode.httpCode == -1", new Object[0]);
|
||||
}
|
||||
frameHeader(0, bArr.length + 8, (byte) 7, (byte) 0);
|
||||
this.sink.writeInt(i);
|
||||
this.sink.writeInt(errorCode.httpCode);
|
||||
if (bArr.length > 0) {
|
||||
this.sink.write(bArr);
|
||||
}
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public synchronized void headers(int i, List<Header> list) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
headers(false, i, list);
|
||||
}
|
||||
|
||||
public int maxDataLength() {
|
||||
return this.maxFrameSize;
|
||||
}
|
||||
|
||||
public synchronized void ping(boolean z, int i, int i2) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
frameHeader(0, 8, (byte) 6, z ? (byte) 1 : (byte) 0);
|
||||
this.sink.writeInt(i);
|
||||
this.sink.writeInt(i2);
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public synchronized void pushPromise(int i, int i2, List<Header> list) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
this.hpackWriter.writeHeaders(list);
|
||||
long size = this.hpackBuffer.size();
|
||||
int min = (int) Math.min(this.maxFrameSize - 4, size);
|
||||
long j = min;
|
||||
frameHeader(i, min + 4, (byte) 5, size == j ? (byte) 4 : (byte) 0);
|
||||
this.sink.writeInt(i2 & Integer.MAX_VALUE);
|
||||
this.sink.write(this.hpackBuffer, j);
|
||||
if (size > j) {
|
||||
writeContinuationFrames(i, size - j);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void rstStream(int i, ErrorCode errorCode) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
if (errorCode.httpCode == -1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
frameHeader(i, 4, (byte) 3, (byte) 0);
|
||||
this.sink.writeInt(errorCode.httpCode);
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public synchronized void settings(Settings settings) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
int i = 0;
|
||||
frameHeader(0, settings.size() * 6, (byte) 4, (byte) 0);
|
||||
while (i < 10) {
|
||||
if (settings.isSet(i)) {
|
||||
this.sink.writeShort(i == 4 ? 3 : i == 7 ? 4 : i);
|
||||
this.sink.writeInt(settings.get(i));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
public synchronized void synReply(boolean z, int i, List<Header> list) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
headers(z, i, list);
|
||||
}
|
||||
|
||||
public synchronized void synStream(boolean z, int i, int i2, List<Header> list) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
headers(z, i, list);
|
||||
}
|
||||
|
||||
public synchronized void windowUpdate(int i, long j) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
if (j == 0 || j > 2147483647L) {
|
||||
throw Http2.illegalArgument("windowSizeIncrement == 0 || windowSizeIncrement > 0x7fffffffL: %s", Long.valueOf(j));
|
||||
}
|
||||
frameHeader(i, 4, (byte) 8, (byte) 0);
|
||||
this.sink.writeInt((int) j);
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
void headers(boolean z, int i, List<Header> list) throws IOException {
|
||||
if (!this.closed) {
|
||||
this.hpackWriter.writeHeaders(list);
|
||||
long size = this.hpackBuffer.size();
|
||||
int min = (int) Math.min(this.maxFrameSize, size);
|
||||
long j = min;
|
||||
byte b = size == j ? (byte) 4 : (byte) 0;
|
||||
if (z) {
|
||||
b = (byte) (b | 1);
|
||||
}
|
||||
frameHeader(i, min, (byte) 1, b);
|
||||
this.sink.write(this.hpackBuffer, j);
|
||||
if (size > j) {
|
||||
writeContinuationFrames(i, size - j);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new IOException("closed");
|
||||
}
|
||||
}
|
||||
137
sources/okhttp3/internal/http2/Huffman.java
Normal file
137
sources/okhttp3/internal/http2/Huffman.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import com.ijm.dataencryption.de.DataDecryptTool;
|
||||
import com.ubt.jimu.unity.bluetooth.UnityActivity;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import okio.BufferedSink;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class Huffman {
|
||||
private static final int[] CODES = {8184, 8388568, 268435426, 268435427, 268435428, 268435429, 268435430, 268435431, 268435432, 16777194, 1073741820, 268435433, 268435434, 1073741821, 268435435, 268435436, 268435437, 268435438, 268435439, 268435440, 268435441, 268435442, 1073741822, 268435443, 268435444, 268435445, 268435446, 268435447, 268435448, 268435449, 268435450, 268435451, 20, UnityActivity.CODE_AR_GAME, 1017, 4090, 8185, 21, 248, 2042, 1018, 1019, 249, 2043, ItemTouchHelper.Callback.DEFAULT_SWIPE_ANIMATION_DURATION, 22, 23, 24, 0, 1, 2, 25, 26, 27, 28, 29, 30, 31, 92, 251, 32764, 32, 4091, 1020, 8186, 33, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 252, 115, 253, 8187, 524272, 8188, 16380, 34, 32765, 3, 35, 4, 36, 5, 37, 38, 39, 6, 116, 117, 40, 41, 42, 7, 43, 118, 44, 8, 9, 45, 119, 120, 121, 122, 123, 32766, 2044, 16381, 8189, 268435452, 1048550, 4194258, 1048551, 1048552, 4194259, 4194260, 4194261, 8388569, 4194262, 8388570, 8388571, 8388572, 8388573, 8388574, 16777195, 8388575, 16777196, 16777197, 4194263, 8388576, 16777198, 8388577, 8388578, 8388579, 8388580, 2097116, 4194264, 8388581, 4194265, 8388582, 8388583, 16777199, 4194266, 2097117, 1048553, 4194267, 4194268, 8388584, 8388585, 2097118, 8388586, 4194269, 4194270, 16777200, 2097119, 4194271, 8388587, 8388588, 2097120, 2097121, 4194272, 2097122, 8388589, 4194273, 8388590, 8388591, 1048554, 4194274, 4194275, 4194276, 8388592, 4194277, 4194278, 8388593, 67108832, 67108833, 1048555, 524273, 4194279, 8388594, 4194280, 33554412, 67108834, 67108835, 67108836, 134217694, 134217695, 67108837, 16777201, 33554413, 524274, 2097123, 67108838, 134217696, 134217697, 67108839, 134217698, 16777202, 2097124, 2097125, 67108840, 67108841, 268435453, 134217699, 134217700, 134217701, 1048556, 16777203, 1048557, 2097126, 4194281, 2097127, 2097128, 8388595, 4194282, 4194283, 33554414, 33554415, 16777204, 16777205, 67108842, 8388596, 67108843, 134217702, 67108844, 67108845, 134217703, 134217704, 134217705, 134217706, 134217707, 268435454, 134217708, 134217709, 134217710, 134217711, 134217712, 67108846};
|
||||
private static final byte[] CODE_LENGTHS = {13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28, 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5, 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23, 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24, 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25, 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26};
|
||||
private static final Huffman INSTANCE = new Huffman();
|
||||
private final Node root = new Node();
|
||||
|
||||
private Huffman() {
|
||||
buildTree();
|
||||
}
|
||||
|
||||
private void addCode(int i, int i2, byte b) {
|
||||
Node node = new Node(i, b);
|
||||
Node node2 = this.root;
|
||||
while (b > 8) {
|
||||
b = (byte) (b - 8);
|
||||
int i3 = (i2 >>> b) & 255;
|
||||
Node[] nodeArr = node2.children;
|
||||
if (nodeArr == null) {
|
||||
throw new IllegalStateException("invalid dictionary: prefix not unique");
|
||||
}
|
||||
if (nodeArr[i3] == null) {
|
||||
nodeArr[i3] = new Node();
|
||||
}
|
||||
node2 = node2.children[i3];
|
||||
}
|
||||
int i4 = 8 - b;
|
||||
int i5 = (i2 << i4) & 255;
|
||||
int i6 = 1 << i4;
|
||||
for (int i7 = i5; i7 < i5 + i6; i7++) {
|
||||
node2.children[i7] = node;
|
||||
}
|
||||
}
|
||||
|
||||
private void buildTree() {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte[] bArr = CODE_LENGTHS;
|
||||
if (i >= bArr.length) {
|
||||
return;
|
||||
}
|
||||
addCode(i, CODES[i], bArr[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public static Huffman get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
byte[] decode(byte[] bArr) {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
Node node = this.root;
|
||||
int i = 0;
|
||||
int i2 = 0;
|
||||
for (byte b : bArr) {
|
||||
i = (i << 8) | (b & 255);
|
||||
i2 += 8;
|
||||
while (i2 >= 8) {
|
||||
node = node.children[(i >>> (i2 - 8)) & 255];
|
||||
if (node.children == null) {
|
||||
byteArrayOutputStream.write(node.symbol);
|
||||
i2 -= node.terminalBits;
|
||||
node = this.root;
|
||||
} else {
|
||||
i2 -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i2 > 0) {
|
||||
Node node2 = node.children[(i << (8 - i2)) & 255];
|
||||
if (node2.children != null || node2.terminalBits > i2) {
|
||||
break;
|
||||
}
|
||||
byteArrayOutputStream.write(node2.symbol);
|
||||
i2 -= node2.terminalBits;
|
||||
node = this.root;
|
||||
}
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
void encode(ByteString byteString, BufferedSink bufferedSink) throws IOException {
|
||||
long j = 0;
|
||||
int i = 0;
|
||||
for (int i2 = 0; i2 < byteString.size(); i2++) {
|
||||
int i3 = byteString.getByte(i2) & 255;
|
||||
int i4 = CODES[i3];
|
||||
byte b = CODE_LENGTHS[i3];
|
||||
j = (j << b) | i4;
|
||||
i += b;
|
||||
while (i >= 8) {
|
||||
i -= 8;
|
||||
bufferedSink.writeByte((int) (j >> i));
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
bufferedSink.writeByte((int) ((255 >>> i) | (j << (8 - i))));
|
||||
}
|
||||
}
|
||||
|
||||
int encodedLength(ByteString byteString) {
|
||||
long j = 0;
|
||||
for (int i = 0; i < byteString.size(); i++) {
|
||||
j += CODE_LENGTHS[byteString.getByte(i) & 255];
|
||||
}
|
||||
return (int) ((j + 7) >> 3);
|
||||
}
|
||||
|
||||
private static final class Node {
|
||||
final Node[] children;
|
||||
final int symbol;
|
||||
final int terminalBits;
|
||||
|
||||
Node() {
|
||||
this.children = new Node[DataDecryptTool.DECRYPT_ALL_FILE];
|
||||
this.symbol = 0;
|
||||
this.terminalBits = 0;
|
||||
}
|
||||
|
||||
Node(int i, int i2) {
|
||||
this.children = null;
|
||||
this.symbol = i;
|
||||
int i3 = i2 & 7;
|
||||
this.terminalBits = i3 == 0 ? 8 : i3;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
sources/okhttp3/internal/http2/PushObserver.java
Normal file
38
sources/okhttp3/internal/http2/PushObserver.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import okio.BufferedSource;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface PushObserver {
|
||||
public static final PushObserver CANCEL = new PushObserver() { // from class: okhttp3.internal.http2.PushObserver.1
|
||||
@Override // okhttp3.internal.http2.PushObserver
|
||||
public boolean onData(int i, BufferedSource bufferedSource, int i2, boolean z) throws IOException {
|
||||
bufferedSource.skip(i2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.PushObserver
|
||||
public boolean onHeaders(int i, List<Header> list, boolean z) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.PushObserver
|
||||
public boolean onRequest(int i, List<Header> list) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.http2.PushObserver
|
||||
public void onReset(int i, ErrorCode errorCode) {
|
||||
}
|
||||
};
|
||||
|
||||
boolean onData(int i, BufferedSource bufferedSource, int i2, boolean z) throws IOException;
|
||||
|
||||
boolean onHeaders(int i, List<Header> list, boolean z);
|
||||
|
||||
boolean onRequest(int i, List<Header> list);
|
||||
|
||||
void onReset(int i, ErrorCode errorCode);
|
||||
}
|
||||
81
sources/okhttp3/internal/http2/Settings.java
Normal file
81
sources/okhttp3/internal/http2/Settings.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import com.ubtrobot.jimu.robotapi.PeripheralType;
|
||||
import java.util.Arrays;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class Settings {
|
||||
static final int COUNT = 10;
|
||||
static final int DEFAULT_INITIAL_WINDOW_SIZE = 65535;
|
||||
static final int ENABLE_PUSH = 2;
|
||||
static final int HEADER_TABLE_SIZE = 1;
|
||||
static final int INITIAL_WINDOW_SIZE = 7;
|
||||
static final int MAX_CONCURRENT_STREAMS = 4;
|
||||
static final int MAX_FRAME_SIZE = 5;
|
||||
static final int MAX_HEADER_LIST_SIZE = 6;
|
||||
private int set;
|
||||
private final int[] values = new int[10];
|
||||
|
||||
void clear() {
|
||||
this.set = 0;
|
||||
Arrays.fill(this.values, 0);
|
||||
}
|
||||
|
||||
int get(int i) {
|
||||
return this.values[i];
|
||||
}
|
||||
|
||||
boolean getEnablePush(boolean z) {
|
||||
return ((this.set & 4) != 0 ? this.values[2] : z ? 1 : 0) == 1;
|
||||
}
|
||||
|
||||
int getHeaderTableSize() {
|
||||
if ((this.set & 2) != 0) {
|
||||
return this.values[1];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getInitialWindowSize() {
|
||||
return (this.set & PeripheralType.SERVO) != 0 ? this.values[7] : DEFAULT_INITIAL_WINDOW_SIZE;
|
||||
}
|
||||
|
||||
int getMaxConcurrentStreams(int i) {
|
||||
return (this.set & 16) != 0 ? this.values[4] : i;
|
||||
}
|
||||
|
||||
int getMaxFrameSize(int i) {
|
||||
return (this.set & 32) != 0 ? this.values[5] : i;
|
||||
}
|
||||
|
||||
int getMaxHeaderListSize(int i) {
|
||||
return (this.set & 64) != 0 ? this.values[6] : i;
|
||||
}
|
||||
|
||||
boolean isSet(int i) {
|
||||
return ((1 << i) & this.set) != 0;
|
||||
}
|
||||
|
||||
void merge(Settings settings) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (settings.isSet(i)) {
|
||||
set(i, settings.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Settings set(int i, int i2) {
|
||||
if (i >= 0) {
|
||||
int[] iArr = this.values;
|
||||
if (i < iArr.length) {
|
||||
this.set = (1 << i) | this.set;
|
||||
iArr[i] = i2;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
int size() {
|
||||
return Integer.bitCount(this.set);
|
||||
}
|
||||
}
|
||||
13
sources/okhttp3/internal/http2/StreamResetException.java
Normal file
13
sources/okhttp3/internal/http2/StreamResetException.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package okhttp3.internal.http2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class StreamResetException extends IOException {
|
||||
public final ErrorCode errorCode;
|
||||
|
||||
public StreamResetException(ErrorCode errorCode) {
|
||||
super("stream was reset: " + errorCode);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
}
|
||||
97
sources/okhttp3/internal/io/FileSystem.java
Normal file
97
sources/okhttp3/internal/io/FileSystem.java
Normal file
@@ -0,0 +1,97 @@
|
||||
package okhttp3.internal.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface FileSystem {
|
||||
public static final FileSystem SYSTEM = new FileSystem() { // from class: okhttp3.internal.io.FileSystem.1
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public Sink appendingSink(File file) throws FileNotFoundException {
|
||||
try {
|
||||
return Okio.appendingSink(file);
|
||||
} catch (FileNotFoundException unused) {
|
||||
file.getParentFile().mkdirs();
|
||||
return Okio.appendingSink(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public void delete(File file) throws IOException {
|
||||
if (file.delete() || !file.exists()) {
|
||||
return;
|
||||
}
|
||||
throw new IOException("failed to delete " + file);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public void deleteContents(File file) throws IOException {
|
||||
File[] listFiles = file.listFiles();
|
||||
if (listFiles == null) {
|
||||
throw new IOException("not a readable directory: " + file);
|
||||
}
|
||||
for (File file2 : listFiles) {
|
||||
if (file2.isDirectory()) {
|
||||
deleteContents(file2);
|
||||
}
|
||||
if (!file2.delete()) {
|
||||
throw new IOException("failed to delete " + file2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public boolean exists(File file) {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public void rename(File file, File file2) throws IOException {
|
||||
delete(file2);
|
||||
if (file.renameTo(file2)) {
|
||||
return;
|
||||
}
|
||||
throw new IOException("failed to rename " + file + " to " + file2);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public Sink sink(File file) throws FileNotFoundException {
|
||||
try {
|
||||
return Okio.sink(file);
|
||||
} catch (FileNotFoundException unused) {
|
||||
file.getParentFile().mkdirs();
|
||||
return Okio.sink(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public long size(File file) {
|
||||
return file.length();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.io.FileSystem
|
||||
public Source source(File file) throws FileNotFoundException {
|
||||
return Okio.source(file);
|
||||
}
|
||||
};
|
||||
|
||||
Sink appendingSink(File file) throws FileNotFoundException;
|
||||
|
||||
void delete(File file) throws IOException;
|
||||
|
||||
void deleteContents(File file) throws IOException;
|
||||
|
||||
boolean exists(File file);
|
||||
|
||||
void rename(File file, File file2) throws IOException;
|
||||
|
||||
Sink sink(File file) throws FileNotFoundException;
|
||||
|
||||
long size(File file);
|
||||
|
||||
Source source(File file) throws FileNotFoundException;
|
||||
}
|
||||
379
sources/okhttp3/internal/platform/AndroidPlatform.java
Normal file
379
sources/okhttp3/internal/platform/AndroidPlatform.java
Normal file
@@ -0,0 +1,379 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Security;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.TrustAnchor;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.tls.CertificateChainCleaner;
|
||||
import okhttp3.internal.tls.TrustRootIndex;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class AndroidPlatform extends Platform {
|
||||
private static final int MAX_LOG_LENGTH = 4000;
|
||||
private final CloseGuard closeGuard = CloseGuard.get();
|
||||
private final OptionalMethod<Socket> getAlpnSelectedProtocol;
|
||||
private final OptionalMethod<Socket> setAlpnProtocols;
|
||||
private final OptionalMethod<Socket> setHostname;
|
||||
private final OptionalMethod<Socket> setUseSessionTickets;
|
||||
private final Class<?> sslParametersClass;
|
||||
|
||||
static final class AndroidCertificateChainCleaner extends CertificateChainCleaner {
|
||||
private final Method checkServerTrusted;
|
||||
private final Object x509TrustManagerExtensions;
|
||||
|
||||
AndroidCertificateChainCleaner(Object obj, Method method) {
|
||||
this.x509TrustManagerExtensions = obj;
|
||||
this.checkServerTrusted = method;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.tls.CertificateChainCleaner
|
||||
public List<Certificate> clean(List<Certificate> list, String str) throws SSLPeerUnverifiedException {
|
||||
try {
|
||||
return (List) this.checkServerTrusted.invoke(this.x509TrustManagerExtensions, (X509Certificate[]) list.toArray(new X509Certificate[list.size()]), "RSA", str);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvocationTargetException e2) {
|
||||
SSLPeerUnverifiedException sSLPeerUnverifiedException = new SSLPeerUnverifiedException(e2.getMessage());
|
||||
sSLPeerUnverifiedException.initCause(e2);
|
||||
throw sSLPeerUnverifiedException;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof AndroidCertificateChainCleaner;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static final class AndroidTrustRootIndex implements TrustRootIndex {
|
||||
private final Method findByIssuerAndSignatureMethod;
|
||||
private final X509TrustManager trustManager;
|
||||
|
||||
AndroidTrustRootIndex(X509TrustManager x509TrustManager, Method method) {
|
||||
this.findByIssuerAndSignatureMethod = method;
|
||||
this.trustManager = x509TrustManager;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof AndroidTrustRootIndex)) {
|
||||
return false;
|
||||
}
|
||||
AndroidTrustRootIndex androidTrustRootIndex = (AndroidTrustRootIndex) obj;
|
||||
return this.trustManager.equals(androidTrustRootIndex.trustManager) && this.findByIssuerAndSignatureMethod.equals(androidTrustRootIndex.findByIssuerAndSignatureMethod);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.tls.TrustRootIndex
|
||||
public X509Certificate findByIssuerAndSignature(X509Certificate x509Certificate) {
|
||||
try {
|
||||
TrustAnchor trustAnchor = (TrustAnchor) this.findByIssuerAndSignatureMethod.invoke(this.trustManager, x509Certificate);
|
||||
if (trustAnchor != null) {
|
||||
return trustAnchor.getTrustedCert();
|
||||
}
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
throw Util.assertionError("unable to get issues and signature", e);
|
||||
} catch (InvocationTargetException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.trustManager.hashCode() + (this.findByIssuerAndSignatureMethod.hashCode() * 31);
|
||||
}
|
||||
}
|
||||
|
||||
static final class CloseGuard {
|
||||
private final Method getMethod;
|
||||
private final Method openMethod;
|
||||
private final Method warnIfOpenMethod;
|
||||
|
||||
CloseGuard(Method method, Method method2, Method method3) {
|
||||
this.getMethod = method;
|
||||
this.openMethod = method2;
|
||||
this.warnIfOpenMethod = method3;
|
||||
}
|
||||
|
||||
static CloseGuard get() {
|
||||
Method method;
|
||||
Method method2;
|
||||
Method method3 = null;
|
||||
try {
|
||||
Class<?> cls = Class.forName("dalvik.system.CloseGuard");
|
||||
Method method4 = cls.getMethod("get", new Class[0]);
|
||||
method2 = cls.getMethod("open", String.class);
|
||||
method = cls.getMethod("warnIfOpen", new Class[0]);
|
||||
method3 = method4;
|
||||
} catch (Exception unused) {
|
||||
method = null;
|
||||
method2 = null;
|
||||
}
|
||||
return new CloseGuard(method3, method2, method);
|
||||
}
|
||||
|
||||
Object createAndOpen(String str) {
|
||||
Method method = this.getMethod;
|
||||
if (method != null) {
|
||||
try {
|
||||
Object invoke = method.invoke(null, new Object[0]);
|
||||
this.openMethod.invoke(invoke, str);
|
||||
return invoke;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean warnIfOpen(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
this.warnIfOpenMethod.invoke(obj, new Object[0]);
|
||||
return true;
|
||||
} catch (Exception unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AndroidPlatform(Class<?> cls, OptionalMethod<Socket> optionalMethod, OptionalMethod<Socket> optionalMethod2, OptionalMethod<Socket> optionalMethod3, OptionalMethod<Socket> optionalMethod4) {
|
||||
this.sslParametersClass = cls;
|
||||
this.setUseSessionTickets = optionalMethod;
|
||||
this.setHostname = optionalMethod2;
|
||||
this.getAlpnSelectedProtocol = optionalMethod3;
|
||||
this.setAlpnProtocols = optionalMethod4;
|
||||
}
|
||||
|
||||
private boolean api23IsCleartextTrafficPermitted(String str, Class<?> cls, Object obj) throws InvocationTargetException, IllegalAccessException {
|
||||
try {
|
||||
return ((Boolean) cls.getMethod("isCleartextTrafficPermitted", new Class[0]).invoke(obj, new Object[0])).booleanValue();
|
||||
} catch (NoSuchMethodException unused) {
|
||||
return super.isCleartextTrafficPermitted(str);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean api24IsCleartextTrafficPermitted(String str, Class<?> cls, Object obj) throws InvocationTargetException, IllegalAccessException {
|
||||
try {
|
||||
return ((Boolean) cls.getMethod("isCleartextTrafficPermitted", String.class).invoke(obj, str)).booleanValue();
|
||||
} catch (NoSuchMethodException unused) {
|
||||
return api23IsCleartextTrafficPermitted(str, cls, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform buildIfSupported() {
|
||||
Class<?> cls;
|
||||
OptionalMethod optionalMethod;
|
||||
OptionalMethod optionalMethod2;
|
||||
try {
|
||||
try {
|
||||
cls = Class.forName("com.android.org.conscrypt.SSLParametersImpl");
|
||||
} catch (ClassNotFoundException unused) {
|
||||
cls = Class.forName("org.apache.harmony.xnet.provider.jsse.SSLParametersImpl");
|
||||
}
|
||||
Class<?> cls2 = cls;
|
||||
OptionalMethod optionalMethod3 = new OptionalMethod(null, "setUseSessionTickets", Boolean.TYPE);
|
||||
OptionalMethod optionalMethod4 = new OptionalMethod(null, "setHostname", String.class);
|
||||
if (supportsAlpn()) {
|
||||
OptionalMethod optionalMethod5 = new OptionalMethod(byte[].class, "getAlpnSelectedProtocol", new Class[0]);
|
||||
optionalMethod2 = new OptionalMethod(null, "setAlpnProtocols", byte[].class);
|
||||
optionalMethod = optionalMethod5;
|
||||
} else {
|
||||
optionalMethod = null;
|
||||
optionalMethod2 = null;
|
||||
}
|
||||
return new AndroidPlatform(cls2, optionalMethod3, optionalMethod4, optionalMethod, optionalMethod2);
|
||||
} catch (ClassNotFoundException unused2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean supportsAlpn() {
|
||||
if (Security.getProvider("GMSCore_OpenSSL") != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
Class.forName("android.net.Network");
|
||||
return true;
|
||||
} catch (ClassNotFoundException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public CertificateChainCleaner buildCertificateChainCleaner(X509TrustManager x509TrustManager) {
|
||||
try {
|
||||
Class<?> cls = Class.forName("android.net.http.X509TrustManagerExtensions");
|
||||
return new AndroidCertificateChainCleaner(cls.getConstructor(X509TrustManager.class).newInstance(x509TrustManager), cls.getMethod("checkServerTrusted", X509Certificate[].class, String.class, String.class));
|
||||
} catch (Exception unused) {
|
||||
return super.buildCertificateChainCleaner(x509TrustManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public TrustRootIndex buildTrustRootIndex(X509TrustManager x509TrustManager) {
|
||||
try {
|
||||
Method declaredMethod = x509TrustManager.getClass().getDeclaredMethod("findTrustAnchorByIssuerAndSignature", X509Certificate.class);
|
||||
declaredMethod.setAccessible(true);
|
||||
return new AndroidTrustRootIndex(x509TrustManager, declaredMethod);
|
||||
} catch (NoSuchMethodException unused) {
|
||||
return super.buildTrustRootIndex(x509TrustManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void configureTlsExtensions(SSLSocket sSLSocket, String str, List<Protocol> list) {
|
||||
if (str != null) {
|
||||
this.setUseSessionTickets.invokeOptionalWithoutCheckedException(sSLSocket, true);
|
||||
this.setHostname.invokeOptionalWithoutCheckedException(sSLSocket, str);
|
||||
}
|
||||
OptionalMethod<Socket> optionalMethod = this.setAlpnProtocols;
|
||||
if (optionalMethod == null || !optionalMethod.isSupported(sSLSocket)) {
|
||||
return;
|
||||
}
|
||||
this.setAlpnProtocols.invokeWithoutCheckedException(sSLSocket, Platform.concatLengthPrefixed(list));
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void connectSocket(Socket socket, InetSocketAddress inetSocketAddress, int i) throws IOException {
|
||||
try {
|
||||
socket.connect(inetSocketAddress, i);
|
||||
} catch (AssertionError e) {
|
||||
if (!Util.isAndroidGetsocknameError(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new IOException(e);
|
||||
} catch (ClassCastException e2) {
|
||||
if (Build.VERSION.SDK_INT != 26) {
|
||||
throw e2;
|
||||
}
|
||||
IOException iOException = new IOException("Exception in connect");
|
||||
iOException.initCause(e2);
|
||||
throw iOException;
|
||||
} catch (SecurityException e3) {
|
||||
IOException iOException2 = new IOException("Exception in connect");
|
||||
iOException2.initCause(e3);
|
||||
throw iOException2;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public SSLContext getSSLContext() {
|
||||
int i = Build.VERSION.SDK_INT;
|
||||
if (i >= 16 && i < 22) {
|
||||
try {
|
||||
return SSLContext.getInstance("TLSv1.2");
|
||||
} catch (NoSuchAlgorithmException unused) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return SSLContext.getInstance("TLS");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("No TLS provider", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public String getSelectedProtocol(SSLSocket sSLSocket) {
|
||||
byte[] bArr;
|
||||
OptionalMethod<Socket> optionalMethod = this.getAlpnSelectedProtocol;
|
||||
if (optionalMethod == null || !optionalMethod.isSupported(sSLSocket) || (bArr = (byte[]) this.getAlpnSelectedProtocol.invokeWithoutCheckedException(sSLSocket, new Object[0])) == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(bArr, Util.UTF_8);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public Object getStackTraceForCloseable(String str) {
|
||||
return this.closeGuard.createAndOpen(str);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public boolean isCleartextTrafficPermitted(String str) {
|
||||
try {
|
||||
Class<?> cls = Class.forName("android.security.NetworkSecurityPolicy");
|
||||
return api24IsCleartextTrafficPermitted(str, cls, cls.getMethod("getInstance", new Class[0]).invoke(null, new Object[0]));
|
||||
} catch (ClassNotFoundException | NoSuchMethodException unused) {
|
||||
return super.isCleartextTrafficPermitted(str);
|
||||
} catch (IllegalAccessException e) {
|
||||
e = e;
|
||||
throw Util.assertionError("unable to determine cleartext support", e);
|
||||
} catch (IllegalArgumentException e2) {
|
||||
e = e2;
|
||||
throw Util.assertionError("unable to determine cleartext support", e);
|
||||
} catch (InvocationTargetException e3) {
|
||||
e = e3;
|
||||
throw Util.assertionError("unable to determine cleartext support", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void log(int i, String str, Throwable th) {
|
||||
int min;
|
||||
int i2 = i != 5 ? 3 : 5;
|
||||
if (th != null) {
|
||||
str = str + '\n' + Log.getStackTraceString(th);
|
||||
}
|
||||
int i3 = 0;
|
||||
int length = str.length();
|
||||
while (i3 < length) {
|
||||
int indexOf = str.indexOf(10, i3);
|
||||
if (indexOf == -1) {
|
||||
indexOf = length;
|
||||
}
|
||||
while (true) {
|
||||
min = Math.min(indexOf, i3 + MAX_LOG_LENGTH);
|
||||
Log.println(i2, "OkHttp", str.substring(i3, min));
|
||||
if (min >= indexOf) {
|
||||
break;
|
||||
} else {
|
||||
i3 = min;
|
||||
}
|
||||
}
|
||||
i3 = min + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void logCloseableLeak(String str, Object obj) {
|
||||
if (this.closeGuard.warnIfOpen(obj)) {
|
||||
return;
|
||||
}
|
||||
log(5, str, null);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
protected X509TrustManager trustManager(SSLSocketFactory sSLSocketFactory) {
|
||||
Object readFieldOrNull = Platform.readFieldOrNull(sSLSocketFactory, this.sslParametersClass, "sslParameters");
|
||||
if (readFieldOrNull == null) {
|
||||
try {
|
||||
readFieldOrNull = Platform.readFieldOrNull(sSLSocketFactory, Class.forName("com.google.android.gms.org.conscrypt.SSLParametersImpl", false, sSLSocketFactory.getClass().getClassLoader()), "sslParameters");
|
||||
} catch (ClassNotFoundException unused) {
|
||||
return super.trustManager(sSLSocketFactory);
|
||||
}
|
||||
}
|
||||
X509TrustManager x509TrustManager = (X509TrustManager) Platform.readFieldOrNull(readFieldOrNull, X509TrustManager.class, "x509TrustManager");
|
||||
return x509TrustManager != null ? x509TrustManager : (X509TrustManager) Platform.readFieldOrNull(readFieldOrNull, X509TrustManager.class, "trustManager");
|
||||
}
|
||||
}
|
||||
84
sources/okhttp3/internal/platform/ConscryptPlatform.java
Normal file
84
sources/okhttp3/internal/platform/ConscryptPlatform.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Protocol;
|
||||
import org.conscrypt.Conscrypt;
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public class ConscryptPlatform extends Platform {
|
||||
private ConscryptPlatform() {
|
||||
}
|
||||
|
||||
public static Platform buildIfSupported() {
|
||||
try {
|
||||
Class.forName("org.conscrypt.ConscryptEngineSocket");
|
||||
if (Conscrypt.isAvailable()) {
|
||||
return new ConscryptPlatform();
|
||||
}
|
||||
return null;
|
||||
} catch (ClassNotFoundException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Provider getProvider() {
|
||||
return new OpenSSLProvider();
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void configureSslSocketFactory(SSLSocketFactory sSLSocketFactory) {
|
||||
if (Conscrypt.isConscrypt(sSLSocketFactory)) {
|
||||
Conscrypt.setUseEngineSocket(sSLSocketFactory, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void configureTlsExtensions(SSLSocket sSLSocket, String str, List<Protocol> list) {
|
||||
if (!Conscrypt.isConscrypt(sSLSocket)) {
|
||||
super.configureTlsExtensions(sSLSocket, str, list);
|
||||
return;
|
||||
}
|
||||
if (str != null) {
|
||||
Conscrypt.setUseSessionTickets(sSLSocket, true);
|
||||
Conscrypt.setHostname(sSLSocket, str);
|
||||
}
|
||||
Conscrypt.setApplicationProtocols(sSLSocket, (String[]) Platform.alpnProtocolNames(list).toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public SSLContext getSSLContext() {
|
||||
try {
|
||||
return SSLContext.getInstance("TLS", getProvider());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("No TLS provider", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public String getSelectedProtocol(SSLSocket sSLSocket) {
|
||||
return Conscrypt.isConscrypt(sSLSocket) ? Conscrypt.getApplicationProtocol(sSLSocket) : super.getSelectedProtocol(sSLSocket);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public X509TrustManager trustManager(SSLSocketFactory sSLSocketFactory) {
|
||||
if (!Conscrypt.isConscrypt(sSLSocketFactory)) {
|
||||
return super.trustManager(sSLSocketFactory);
|
||||
}
|
||||
try {
|
||||
Object readFieldOrNull = Platform.readFieldOrNull(sSLSocketFactory, Object.class, "sslParameters");
|
||||
if (readFieldOrNull != null) {
|
||||
return (X509TrustManager) Platform.readFieldOrNull(readFieldOrNull, X509TrustManager.class, "x509TrustManager");
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new UnsupportedOperationException("clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on Conscrypt", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
sources/okhttp3/internal/platform/Jdk9Platform.java
Normal file
63
sources/okhttp3/internal/platform/Jdk9Platform.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class Jdk9Platform extends Platform {
|
||||
final Method getProtocolMethod;
|
||||
final Method setProtocolMethod;
|
||||
|
||||
Jdk9Platform(Method method, Method method2) {
|
||||
this.setProtocolMethod = method;
|
||||
this.getProtocolMethod = method2;
|
||||
}
|
||||
|
||||
public static Jdk9Platform buildIfSupported() {
|
||||
try {
|
||||
return new Jdk9Platform(SSLParameters.class.getMethod("setApplicationProtocols", String[].class), SSLSocket.class.getMethod("getApplicationProtocol", new Class[0]));
|
||||
} catch (NoSuchMethodException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void configureTlsExtensions(SSLSocket sSLSocket, String str, List<Protocol> list) {
|
||||
try {
|
||||
SSLParameters sSLParameters = sSLSocket.getSSLParameters();
|
||||
List<String> alpnProtocolNames = Platform.alpnProtocolNames(list);
|
||||
this.setProtocolMethod.invoke(sSLParameters, alpnProtocolNames.toArray(new String[alpnProtocolNames.size()]));
|
||||
sSLSocket.setSSLParameters(sSLParameters);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw Util.assertionError("unable to set ssl parameters", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public String getSelectedProtocol(SSLSocket sSLSocket) {
|
||||
try {
|
||||
String str = (String) this.getProtocolMethod.invoke(sSLSocket, new Object[0]);
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
if (str.equals("")) {
|
||||
return null;
|
||||
}
|
||||
return str;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw Util.assertionError("unable to get selected protocols", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public X509TrustManager trustManager(SSLSocketFactory sSLSocketFactory) {
|
||||
throw new UnsupportedOperationException("clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9+");
|
||||
}
|
||||
}
|
||||
120
sources/okhttp3/internal/platform/JdkWithJettyBootPlatform.java
Normal file
120
sources/okhttp3/internal/platform/JdkWithJettyBootPlatform.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class JdkWithJettyBootPlatform extends Platform {
|
||||
private final Class<?> clientProviderClass;
|
||||
private final Method getMethod;
|
||||
private final Method putMethod;
|
||||
private final Method removeMethod;
|
||||
private final Class<?> serverProviderClass;
|
||||
|
||||
private static class JettyNegoProvider implements InvocationHandler {
|
||||
private final List<String> protocols;
|
||||
String selected;
|
||||
boolean unsupported;
|
||||
|
||||
JettyNegoProvider(List<String> list) {
|
||||
this.protocols = list;
|
||||
}
|
||||
|
||||
@Override // java.lang.reflect.InvocationHandler
|
||||
public Object invoke(Object obj, Method method, Object[] objArr) throws Throwable {
|
||||
String name = method.getName();
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (objArr == null) {
|
||||
objArr = Util.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
if (name.equals("supports") && Boolean.TYPE == returnType) {
|
||||
return true;
|
||||
}
|
||||
if (name.equals("unsupported") && Void.TYPE == returnType) {
|
||||
this.unsupported = true;
|
||||
return null;
|
||||
}
|
||||
if (name.equals("protocols") && objArr.length == 0) {
|
||||
return this.protocols;
|
||||
}
|
||||
if ((!name.equals("selectProtocol") && !name.equals("select")) || String.class != returnType || objArr.length != 1 || !(objArr[0] instanceof List)) {
|
||||
if ((!name.equals("protocolSelected") && !name.equals("selected")) || objArr.length != 1) {
|
||||
return method.invoke(this, objArr);
|
||||
}
|
||||
this.selected = (String) objArr[0];
|
||||
return null;
|
||||
}
|
||||
List list = (List) objArr[0];
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (this.protocols.contains(list.get(i))) {
|
||||
String str = (String) list.get(i);
|
||||
this.selected = str;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
String str2 = this.protocols.get(0);
|
||||
this.selected = str2;
|
||||
return str2;
|
||||
}
|
||||
}
|
||||
|
||||
JdkWithJettyBootPlatform(Method method, Method method2, Method method3, Class<?> cls, Class<?> cls2) {
|
||||
this.putMethod = method;
|
||||
this.getMethod = method2;
|
||||
this.removeMethod = method3;
|
||||
this.clientProviderClass = cls;
|
||||
this.serverProviderClass = cls2;
|
||||
}
|
||||
|
||||
public static Platform buildIfSupported() {
|
||||
try {
|
||||
Class<?> cls = Class.forName("org.eclipse.jetty.alpn.ALPN");
|
||||
Class<?> cls2 = Class.forName("org.eclipse.jetty.alpn.ALPN$Provider");
|
||||
return new JdkWithJettyBootPlatform(cls.getMethod("put", SSLSocket.class, cls2), cls.getMethod("get", SSLSocket.class), cls.getMethod("remove", SSLSocket.class), Class.forName("org.eclipse.jetty.alpn.ALPN$ClientProvider"), Class.forName("org.eclipse.jetty.alpn.ALPN$ServerProvider"));
|
||||
} catch (ClassNotFoundException | NoSuchMethodException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void afterHandshake(SSLSocket sSLSocket) {
|
||||
try {
|
||||
this.removeMethod.invoke(null, sSLSocket);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw Util.assertionError("unable to remove alpn", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public void configureTlsExtensions(SSLSocket sSLSocket, String str, List<Protocol> list) {
|
||||
try {
|
||||
this.putMethod.invoke(null, sSLSocket, Proxy.newProxyInstance(Platform.class.getClassLoader(), new Class[]{this.clientProviderClass, this.serverProviderClass}, new JettyNegoProvider(Platform.alpnProtocolNames(list))));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw Util.assertionError("unable to set alpn", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.platform.Platform
|
||||
public String getSelectedProtocol(SSLSocket sSLSocket) {
|
||||
try {
|
||||
JettyNegoProvider jettyNegoProvider = (JettyNegoProvider) Proxy.getInvocationHandler(this.getMethod.invoke(null, sSLSocket));
|
||||
if (!jettyNegoProvider.unsupported && jettyNegoProvider.selected == null) {
|
||||
Platform.get().log(4, "ALPN callback dropped: HTTP/2 is disabled. Is alpn-boot on the boot class path?", null);
|
||||
return null;
|
||||
}
|
||||
if (jettyNegoProvider.unsupported) {
|
||||
return null;
|
||||
}
|
||||
return jettyNegoProvider.selected;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw Util.assertionError("unable to get selected protocol", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
103
sources/okhttp3/internal/platform/OptionalMethod.java
Normal file
103
sources/okhttp3/internal/platform/OptionalMethod.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class OptionalMethod<T> {
|
||||
private final String methodName;
|
||||
private final Class[] methodParams;
|
||||
private final Class<?> returnType;
|
||||
|
||||
OptionalMethod(Class<?> cls, String str, Class... clsArr) {
|
||||
this.returnType = cls;
|
||||
this.methodName = str;
|
||||
this.methodParams = clsArr;
|
||||
}
|
||||
|
||||
private Method getMethod(Class<?> cls) {
|
||||
Class<?> cls2;
|
||||
String str = this.methodName;
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
Method publicMethod = getPublicMethod(cls, str, this.methodParams);
|
||||
if (publicMethod == null || (cls2 = this.returnType) == null || cls2.isAssignableFrom(publicMethod.getReturnType())) {
|
||||
return publicMethod;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method getPublicMethod(Class<?> cls, String str, Class[] clsArr) {
|
||||
try {
|
||||
Method method = cls.getMethod(str, clsArr);
|
||||
try {
|
||||
if ((method.getModifiers() & 1) != 0) {
|
||||
return method;
|
||||
}
|
||||
} catch (NoSuchMethodException unused) {
|
||||
return method;
|
||||
}
|
||||
} catch (NoSuchMethodException unused2) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object invoke(T t, Object... objArr) throws InvocationTargetException {
|
||||
Method method = getMethod(t.getClass());
|
||||
if (method == null) {
|
||||
throw new AssertionError("Method " + this.methodName + " not supported for object " + t);
|
||||
}
|
||||
try {
|
||||
return method.invoke(t, objArr);
|
||||
} catch (IllegalAccessException e) {
|
||||
AssertionError assertionError = new AssertionError("Unexpectedly could not call: " + method);
|
||||
assertionError.initCause(e);
|
||||
throw assertionError;
|
||||
}
|
||||
}
|
||||
|
||||
public Object invokeOptional(T t, Object... objArr) throws InvocationTargetException {
|
||||
Method method = getMethod(t.getClass());
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return method.invoke(t, objArr);
|
||||
} catch (IllegalAccessException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object invokeOptionalWithoutCheckedException(T t, Object... objArr) {
|
||||
try {
|
||||
return invokeOptional(t, objArr);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable targetException = e.getTargetException();
|
||||
if (targetException instanceof RuntimeException) {
|
||||
throw ((RuntimeException) targetException);
|
||||
}
|
||||
AssertionError assertionError = new AssertionError("Unexpected exception");
|
||||
assertionError.initCause(targetException);
|
||||
throw assertionError;
|
||||
}
|
||||
}
|
||||
|
||||
public Object invokeWithoutCheckedException(T t, Object... objArr) {
|
||||
try {
|
||||
return invoke(t, objArr);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable targetException = e.getTargetException();
|
||||
if (targetException instanceof RuntimeException) {
|
||||
throw ((RuntimeException) targetException);
|
||||
}
|
||||
AssertionError assertionError = new AssertionError("Unexpected exception");
|
||||
assertionError.initCause(targetException);
|
||||
throw assertionError;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSupported(T t) {
|
||||
return getMethod(t.getClass()) != null;
|
||||
}
|
||||
}
|
||||
191
sources/okhttp3/internal/platform/Platform.java
Normal file
191
sources/okhttp3/internal/platform/Platform.java
Normal file
@@ -0,0 +1,191 @@
|
||||
package okhttp3.internal.platform;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.internal.tls.BasicCertificateChainCleaner;
|
||||
import okhttp3.internal.tls.BasicTrustRootIndex;
|
||||
import okhttp3.internal.tls.CertificateChainCleaner;
|
||||
import okhttp3.internal.tls.TrustRootIndex;
|
||||
import okio.Buffer;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public class Platform {
|
||||
public static final int INFO = 4;
|
||||
public static final int WARN = 5;
|
||||
private static final Platform PLATFORM = findPlatform();
|
||||
private static final Logger logger = Logger.getLogger(OkHttpClient.class.getName());
|
||||
|
||||
public static List<String> alpnProtocolNames(List<Protocol> list) {
|
||||
ArrayList arrayList = new ArrayList(list.size());
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Protocol protocol = list.get(i);
|
||||
if (protocol != Protocol.HTTP_1_0) {
|
||||
arrayList.add(protocol.toString());
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
static byte[] concatLengthPrefixed(List<Protocol> list) {
|
||||
Buffer buffer = new Buffer();
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Protocol protocol = list.get(i);
|
||||
if (protocol != Protocol.HTTP_1_0) {
|
||||
buffer.writeByte(protocol.toString().length());
|
||||
buffer.writeUtf8(protocol.toString());
|
||||
}
|
||||
}
|
||||
return buffer.readByteArray();
|
||||
}
|
||||
|
||||
private static Platform findPlatform() {
|
||||
Platform buildIfSupported;
|
||||
Platform buildIfSupported2 = AndroidPlatform.buildIfSupported();
|
||||
if (buildIfSupported2 != null) {
|
||||
return buildIfSupported2;
|
||||
}
|
||||
if (isConscryptPreferred() && (buildIfSupported = ConscryptPlatform.buildIfSupported()) != null) {
|
||||
return buildIfSupported;
|
||||
}
|
||||
Jdk9Platform buildIfSupported3 = Jdk9Platform.buildIfSupported();
|
||||
if (buildIfSupported3 != null) {
|
||||
return buildIfSupported3;
|
||||
}
|
||||
Platform buildIfSupported4 = JdkWithJettyBootPlatform.buildIfSupported();
|
||||
return buildIfSupported4 != null ? buildIfSupported4 : new Platform();
|
||||
}
|
||||
|
||||
public static Platform get() {
|
||||
return PLATFORM;
|
||||
}
|
||||
|
||||
public static boolean isConscryptPreferred() {
|
||||
if ("conscrypt".equals(System.getProperty("okhttp.platform"))) {
|
||||
return true;
|
||||
}
|
||||
return "Conscrypt".equals(Security.getProviders()[0].getName());
|
||||
}
|
||||
|
||||
static <T> T readFieldOrNull(Object obj, Class<T> cls, String str) {
|
||||
Object readFieldOrNull;
|
||||
for (Class<?> cls2 = obj.getClass(); cls2 != Object.class; cls2 = cls2.getSuperclass()) {
|
||||
try {
|
||||
Field declaredField = cls2.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
Object obj2 = declaredField.get(obj);
|
||||
if (obj2 != null && cls.isInstance(obj2)) {
|
||||
return cls.cast(obj2);
|
||||
}
|
||||
return null;
|
||||
} catch (IllegalAccessException unused) {
|
||||
throw new AssertionError();
|
||||
} catch (NoSuchFieldException unused2) {
|
||||
}
|
||||
}
|
||||
if (str.equals("delegate") || (readFieldOrNull = readFieldOrNull(obj, Object.class, "delegate")) == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) readFieldOrNull(readFieldOrNull, cls, str);
|
||||
}
|
||||
|
||||
public void afterHandshake(SSLSocket sSLSocket) {
|
||||
}
|
||||
|
||||
public CertificateChainCleaner buildCertificateChainCleaner(X509TrustManager x509TrustManager) {
|
||||
return new BasicCertificateChainCleaner(buildTrustRootIndex(x509TrustManager));
|
||||
}
|
||||
|
||||
public TrustRootIndex buildTrustRootIndex(X509TrustManager x509TrustManager) {
|
||||
return new BasicTrustRootIndex(x509TrustManager.getAcceptedIssuers());
|
||||
}
|
||||
|
||||
public void configureSslSocketFactory(SSLSocketFactory sSLSocketFactory) {
|
||||
}
|
||||
|
||||
public void configureTlsExtensions(SSLSocket sSLSocket, String str, List<Protocol> list) {
|
||||
}
|
||||
|
||||
public void connectSocket(Socket socket, InetSocketAddress inetSocketAddress, int i) throws IOException {
|
||||
socket.connect(inetSocketAddress, i);
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return "OkHttp";
|
||||
}
|
||||
|
||||
public SSLContext getSSLContext() {
|
||||
if ("1.7".equals(System.getProperty("java.specification.version"))) {
|
||||
try {
|
||||
return SSLContext.getInstance("TLSv1.2");
|
||||
} catch (NoSuchAlgorithmException unused) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return SSLContext.getInstance("TLS");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("No TLS provider", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelectedProtocol(SSLSocket sSLSocket) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getStackTraceForCloseable(String str) {
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
return new Throwable(str);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isCleartextTrafficPermitted(String str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void log(int i, String str, Throwable th) {
|
||||
logger.log(i == 5 ? Level.WARNING : Level.INFO, str, th);
|
||||
}
|
||||
|
||||
public void logCloseableLeak(String str, Object obj) {
|
||||
if (obj == null) {
|
||||
str = str + " To see where this was allocated, set the OkHttpClient logger level to FINE: Logger.getLogger(OkHttpClient.class.getName()).setLevel(Level.FINE);";
|
||||
}
|
||||
log(5, str, (Throwable) obj);
|
||||
}
|
||||
|
||||
protected X509TrustManager trustManager(SSLSocketFactory sSLSocketFactory) {
|
||||
try {
|
||||
Object readFieldOrNull = readFieldOrNull(sSLSocketFactory, Class.forName("sun.security.ssl.SSLContextImpl"), "context");
|
||||
if (readFieldOrNull == null) {
|
||||
return null;
|
||||
}
|
||||
return (X509TrustManager) readFieldOrNull(readFieldOrNull, X509TrustManager.class, "trustManager");
|
||||
} catch (ClassNotFoundException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CertificateChainCleaner buildCertificateChainCleaner(SSLSocketFactory sSLSocketFactory) {
|
||||
X509TrustManager trustManager = trustManager(sSLSocketFactory);
|
||||
if (trustManager != null) {
|
||||
return buildCertificateChainCleaner(trustManager);
|
||||
}
|
||||
throw new IllegalStateException("Unable to extract the trust manager on " + get() + ", sslSocketFactory is " + sSLSocketFactory.getClass());
|
||||
}
|
||||
}
|
||||
256
sources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.java
Normal file
256
sources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.java
Normal file
@@ -0,0 +1,256 @@
|
||||
package okhttp3.internal.publicsuffix;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.IDN;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okio.BufferedSource;
|
||||
import okio.GzipSource;
|
||||
import okio.Okio;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class PublicSuffixDatabase {
|
||||
private static final byte EXCEPTION_MARKER = 33;
|
||||
public static final String PUBLIC_SUFFIX_RESOURCE = "publicsuffixes.gz";
|
||||
private byte[] publicSuffixExceptionListBytes;
|
||||
private byte[] publicSuffixListBytes;
|
||||
private static final byte[] WILDCARD_LABEL = {42};
|
||||
private static final String[] EMPTY_RULE = new String[0];
|
||||
private static final String[] PREVAILING_RULE = {"*"};
|
||||
private static final PublicSuffixDatabase instance = new PublicSuffixDatabase();
|
||||
private final AtomicBoolean listRead = new AtomicBoolean(false);
|
||||
private final CountDownLatch readCompleteLatch = new CountDownLatch(1);
|
||||
|
||||
private static String binarySearchBytes(byte[] bArr, byte[][] bArr2, int i) {
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int length = bArr.length;
|
||||
int i5 = 0;
|
||||
while (i5 < length) {
|
||||
int i6 = (i5 + length) / 2;
|
||||
while (i6 > -1 && bArr[i6] != 10) {
|
||||
i6--;
|
||||
}
|
||||
int i7 = i6 + 1;
|
||||
int i8 = 1;
|
||||
while (true) {
|
||||
i2 = i7 + i8;
|
||||
if (bArr[i2] == 10) {
|
||||
break;
|
||||
}
|
||||
i8++;
|
||||
}
|
||||
int i9 = i2 - i7;
|
||||
int i10 = i;
|
||||
boolean z = false;
|
||||
int i11 = 0;
|
||||
int i12 = 0;
|
||||
while (true) {
|
||||
if (z) {
|
||||
z = false;
|
||||
i3 = 46;
|
||||
} else {
|
||||
i3 = bArr2[i10][i11] & 255;
|
||||
}
|
||||
i4 = i3 - (bArr[i7 + i12] & 255);
|
||||
if (i4 == 0) {
|
||||
i12++;
|
||||
i11++;
|
||||
if (i12 == i9) {
|
||||
break;
|
||||
}
|
||||
if (bArr2[i10].length == i11) {
|
||||
if (i10 == bArr2.length - 1) {
|
||||
break;
|
||||
}
|
||||
i10++;
|
||||
z = true;
|
||||
i11 = -1;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i4 >= 0) {
|
||||
if (i4 <= 0) {
|
||||
int i13 = i9 - i12;
|
||||
int length2 = bArr2[i10].length - i11;
|
||||
while (true) {
|
||||
i10++;
|
||||
if (i10 >= bArr2.length) {
|
||||
break;
|
||||
}
|
||||
length2 += bArr2[i10].length;
|
||||
}
|
||||
if (length2 >= i13) {
|
||||
if (length2 <= i13) {
|
||||
return new String(bArr, i7, i9, Util.UTF_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
i5 = i2 + 1;
|
||||
}
|
||||
length = i7 - 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] findMatchingRule(String[] strArr) {
|
||||
String str;
|
||||
String str2;
|
||||
String str3;
|
||||
if (this.listRead.get() || !this.listRead.compareAndSet(false, true)) {
|
||||
try {
|
||||
this.readCompleteLatch.await();
|
||||
} catch (InterruptedException unused) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
} else {
|
||||
readTheListUninterruptibly();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (this.publicSuffixListBytes == null) {
|
||||
throw new IllegalStateException("Unable to load publicsuffixes.gz resource from the classpath.");
|
||||
}
|
||||
}
|
||||
byte[][] bArr = new byte[strArr.length][];
|
||||
for (int i = 0; i < strArr.length; i++) {
|
||||
bArr[i] = strArr[i].getBytes(Util.UTF_8);
|
||||
}
|
||||
int i2 = 0;
|
||||
while (true) {
|
||||
if (i2 >= bArr.length) {
|
||||
str = null;
|
||||
break;
|
||||
}
|
||||
str = binarySearchBytes(this.publicSuffixListBytes, bArr, i2);
|
||||
if (str != null) {
|
||||
break;
|
||||
}
|
||||
i2++;
|
||||
}
|
||||
if (bArr.length > 1) {
|
||||
byte[][] bArr2 = (byte[][]) bArr.clone();
|
||||
for (int i3 = 0; i3 < bArr2.length - 1; i3++) {
|
||||
bArr2[i3] = WILDCARD_LABEL;
|
||||
str2 = binarySearchBytes(this.publicSuffixListBytes, bArr2, i3);
|
||||
if (str2 != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
str2 = null;
|
||||
if (str2 != null) {
|
||||
for (int i4 = 0; i4 < bArr.length - 1; i4++) {
|
||||
str3 = binarySearchBytes(this.publicSuffixExceptionListBytes, bArr, i4);
|
||||
if (str3 != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
str3 = null;
|
||||
if (str3 != null) {
|
||||
return ("!" + str3).split("\\.");
|
||||
}
|
||||
if (str == null && str2 == null) {
|
||||
return PREVAILING_RULE;
|
||||
}
|
||||
String[] split = str != null ? str.split("\\.") : EMPTY_RULE;
|
||||
String[] split2 = str2 != null ? str2.split("\\.") : EMPTY_RULE;
|
||||
return split.length > split2.length ? split : split2;
|
||||
}
|
||||
|
||||
public static PublicSuffixDatabase get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void readTheList() throws IOException {
|
||||
InputStream resourceAsStream = PublicSuffixDatabase.class.getResourceAsStream(PUBLIC_SUFFIX_RESOURCE);
|
||||
if (resourceAsStream == null) {
|
||||
return;
|
||||
}
|
||||
BufferedSource buffer = Okio.buffer(new GzipSource(Okio.source(resourceAsStream)));
|
||||
try {
|
||||
byte[] bArr = new byte[buffer.readInt()];
|
||||
buffer.readFully(bArr);
|
||||
byte[] bArr2 = new byte[buffer.readInt()];
|
||||
buffer.readFully(bArr2);
|
||||
synchronized (this) {
|
||||
this.publicSuffixListBytes = bArr;
|
||||
this.publicSuffixExceptionListBytes = bArr2;
|
||||
}
|
||||
this.readCompleteLatch.countDown();
|
||||
} finally {
|
||||
Util.closeQuietly(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private void readTheListUninterruptibly() {
|
||||
boolean z = false;
|
||||
while (true) {
|
||||
try {
|
||||
try {
|
||||
readTheList();
|
||||
break;
|
||||
} catch (InterruptedIOException unused) {
|
||||
z = true;
|
||||
} catch (IOException e) {
|
||||
Platform.get().log(5, "Failed to read public suffix list", e);
|
||||
if (z) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
if (z) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
if (z) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public String getEffectiveTldPlusOne(String str) {
|
||||
int length;
|
||||
int length2;
|
||||
if (str == null) {
|
||||
throw new NullPointerException("domain == null");
|
||||
}
|
||||
String[] split = IDN.toUnicode(str).split("\\.");
|
||||
String[] findMatchingRule = findMatchingRule(split);
|
||||
if (split.length == findMatchingRule.length && findMatchingRule[0].charAt(0) != '!') {
|
||||
return null;
|
||||
}
|
||||
if (findMatchingRule[0].charAt(0) == '!') {
|
||||
length = split.length;
|
||||
length2 = findMatchingRule.length;
|
||||
} else {
|
||||
length = split.length;
|
||||
length2 = findMatchingRule.length + 1;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] split2 = str.split("\\.");
|
||||
for (int i = length - length2; i < split2.length; i++) {
|
||||
sb.append(split2[i]);
|
||||
sb.append('.');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
void setListBytes(byte[] bArr, byte[] bArr2) {
|
||||
this.publicSuffixListBytes = bArr;
|
||||
this.publicSuffixExceptionListBytes = bArr2;
|
||||
this.listRead.set(true);
|
||||
this.readCompleteLatch.countDown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class BasicCertificateChainCleaner extends CertificateChainCleaner {
|
||||
private static final int MAX_SIGNERS = 9;
|
||||
private final TrustRootIndex trustRootIndex;
|
||||
|
||||
public BasicCertificateChainCleaner(TrustRootIndex trustRootIndex) {
|
||||
this.trustRootIndex = trustRootIndex;
|
||||
}
|
||||
|
||||
private boolean verifySignature(X509Certificate x509Certificate, X509Certificate x509Certificate2) {
|
||||
if (!x509Certificate.getIssuerDN().equals(x509Certificate2.getSubjectDN())) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
x509Certificate.verify(x509Certificate2.getPublicKey());
|
||||
return true;
|
||||
} catch (GeneralSecurityException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.tls.CertificateChainCleaner
|
||||
public List<Certificate> clean(List<Certificate> list, String str) throws SSLPeerUnverifiedException {
|
||||
ArrayDeque arrayDeque = new ArrayDeque(list);
|
||||
ArrayList arrayList = new ArrayList();
|
||||
arrayList.add(arrayDeque.removeFirst());
|
||||
boolean z = false;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
X509Certificate x509Certificate = (X509Certificate) arrayList.get(arrayList.size() - 1);
|
||||
X509Certificate findByIssuerAndSignature = this.trustRootIndex.findByIssuerAndSignature(x509Certificate);
|
||||
if (findByIssuerAndSignature == null) {
|
||||
Iterator it = arrayDeque.iterator();
|
||||
while (it.hasNext()) {
|
||||
X509Certificate x509Certificate2 = (X509Certificate) it.next();
|
||||
if (verifySignature(x509Certificate, x509Certificate2)) {
|
||||
it.remove();
|
||||
arrayList.add(x509Certificate2);
|
||||
}
|
||||
}
|
||||
if (z) {
|
||||
return arrayList;
|
||||
}
|
||||
throw new SSLPeerUnverifiedException("Failed to find a trusted cert that signed " + x509Certificate);
|
||||
}
|
||||
if (arrayList.size() > 1 || !x509Certificate.equals(findByIssuerAndSignature)) {
|
||||
arrayList.add(findByIssuerAndSignature);
|
||||
}
|
||||
if (verifySignature(findByIssuerAndSignature, findByIssuerAndSignature)) {
|
||||
return arrayList;
|
||||
}
|
||||
z = true;
|
||||
}
|
||||
throw new SSLPeerUnverifiedException("Certificate chain too long: " + arrayList);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
return (obj instanceof BasicCertificateChainCleaner) && ((BasicCertificateChainCleaner) obj).trustRootIndex.equals(this.trustRootIndex);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.trustRootIndex.hashCode();
|
||||
}
|
||||
}
|
||||
52
sources/okhttp3/internal/tls/BasicTrustRootIndex.java
Normal file
52
sources/okhttp3/internal/tls/BasicTrustRootIndex.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class BasicTrustRootIndex implements TrustRootIndex {
|
||||
private final Map<X500Principal, Set<X509Certificate>> subjectToCaCerts = new LinkedHashMap();
|
||||
|
||||
public BasicTrustRootIndex(X509Certificate... x509CertificateArr) {
|
||||
for (X509Certificate x509Certificate : x509CertificateArr) {
|
||||
X500Principal subjectX500Principal = x509Certificate.getSubjectX500Principal();
|
||||
Set<X509Certificate> set = this.subjectToCaCerts.get(subjectX500Principal);
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<>(1);
|
||||
this.subjectToCaCerts.put(subjectX500Principal, set);
|
||||
}
|
||||
set.add(x509Certificate);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
return (obj instanceof BasicTrustRootIndex) && ((BasicTrustRootIndex) obj).subjectToCaCerts.equals(this.subjectToCaCerts);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.tls.TrustRootIndex
|
||||
public X509Certificate findByIssuerAndSignature(X509Certificate x509Certificate) {
|
||||
Set<X509Certificate> set = this.subjectToCaCerts.get(x509Certificate.getIssuerX500Principal());
|
||||
if (set == null) {
|
||||
return null;
|
||||
}
|
||||
for (X509Certificate x509Certificate2 : set) {
|
||||
try {
|
||||
x509Certificate.verify(x509Certificate2.getPublicKey());
|
||||
return x509Certificate2;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.subjectToCaCerts.hashCode();
|
||||
}
|
||||
}
|
||||
21
sources/okhttp3/internal/tls/CertificateChainCleaner.java
Normal file
21
sources/okhttp3/internal/tls/CertificateChainCleaner.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public abstract class CertificateChainCleaner {
|
||||
public static CertificateChainCleaner get(X509TrustManager x509TrustManager) {
|
||||
return Platform.get().buildCertificateChainCleaner(x509TrustManager);
|
||||
}
|
||||
|
||||
public abstract List<Certificate> clean(List<Certificate> list, String str) throws SSLPeerUnverifiedException;
|
||||
|
||||
public static CertificateChainCleaner get(X509Certificate... x509CertificateArr) {
|
||||
return new BasicCertificateChainCleaner(new BasicTrustRootIndex(x509CertificateArr));
|
||||
}
|
||||
}
|
||||
419
sources/okhttp3/internal/tls/DistinguishedNameParser.java
Normal file
419
sources/okhttp3/internal/tls/DistinguishedNameParser.java
Normal file
@@ -0,0 +1,419 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class DistinguishedNameParser {
|
||||
private int beg;
|
||||
private char[] chars;
|
||||
private int cur;
|
||||
private final String dn;
|
||||
private int end;
|
||||
private final int length;
|
||||
private int pos;
|
||||
|
||||
DistinguishedNameParser(X500Principal x500Principal) {
|
||||
this.dn = x500Principal.getName("RFC2253");
|
||||
this.length = this.dn.length();
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:24:0x00a7, code lost:
|
||||
|
||||
return new java.lang.String(r1, r2, r8.cur - r2);
|
||||
*/
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
private java.lang.String escapedAV() {
|
||||
/*
|
||||
r8 = this;
|
||||
int r0 = r8.pos
|
||||
r8.beg = r0
|
||||
r8.end = r0
|
||||
L6:
|
||||
int r0 = r8.pos
|
||||
int r1 = r8.length
|
||||
if (r0 < r1) goto L19
|
||||
java.lang.String r0 = new java.lang.String
|
||||
char[] r1 = r8.chars
|
||||
int r2 = r8.beg
|
||||
int r3 = r8.end
|
||||
int r3 = r3 - r2
|
||||
r0.<init>(r1, r2, r3)
|
||||
return r0
|
||||
L19:
|
||||
char[] r1 = r8.chars
|
||||
char r2 = r1[r0]
|
||||
r3 = 44
|
||||
r4 = 43
|
||||
r5 = 59
|
||||
r6 = 32
|
||||
if (r2 == r6) goto L60
|
||||
if (r2 == r5) goto L53
|
||||
r5 = 92
|
||||
if (r2 == r5) goto L40
|
||||
if (r2 == r4) goto L53
|
||||
if (r2 == r3) goto L53
|
||||
int r2 = r8.end
|
||||
int r3 = r2 + 1
|
||||
r8.end = r3
|
||||
char r3 = r1[r0]
|
||||
r1[r2] = r3
|
||||
int r0 = r0 + 1
|
||||
r8.pos = r0
|
||||
goto L6
|
||||
L40:
|
||||
int r0 = r8.end
|
||||
int r2 = r0 + 1
|
||||
r8.end = r2
|
||||
char r2 = r8.getEscaped()
|
||||
r1[r0] = r2
|
||||
int r0 = r8.pos
|
||||
int r0 = r0 + 1
|
||||
r8.pos = r0
|
||||
goto L6
|
||||
L53:
|
||||
java.lang.String r0 = new java.lang.String
|
||||
char[] r1 = r8.chars
|
||||
int r2 = r8.beg
|
||||
int r3 = r8.end
|
||||
int r3 = r3 - r2
|
||||
r0.<init>(r1, r2, r3)
|
||||
return r0
|
||||
L60:
|
||||
int r2 = r8.end
|
||||
r8.cur = r2
|
||||
int r0 = r0 + 1
|
||||
r8.pos = r0
|
||||
int r0 = r2 + 1
|
||||
r8.end = r0
|
||||
r1[r2] = r6
|
||||
L6e:
|
||||
int r0 = r8.pos
|
||||
int r1 = r8.length
|
||||
if (r0 >= r1) goto L87
|
||||
char[] r1 = r8.chars
|
||||
char r2 = r1[r0]
|
||||
if (r2 != r6) goto L87
|
||||
int r2 = r8.end
|
||||
int r7 = r2 + 1
|
||||
r8.end = r7
|
||||
r1[r2] = r6
|
||||
int r0 = r0 + 1
|
||||
r8.pos = r0
|
||||
goto L6e
|
||||
L87:
|
||||
int r0 = r8.pos
|
||||
int r1 = r8.length
|
||||
if (r0 == r1) goto L9b
|
||||
char[] r1 = r8.chars
|
||||
char r2 = r1[r0]
|
||||
if (r2 == r3) goto L9b
|
||||
char r2 = r1[r0]
|
||||
if (r2 == r4) goto L9b
|
||||
char r0 = r1[r0]
|
||||
if (r0 != r5) goto L6
|
||||
L9b:
|
||||
java.lang.String r0 = new java.lang.String
|
||||
char[] r1 = r8.chars
|
||||
int r2 = r8.beg
|
||||
int r3 = r8.cur
|
||||
int r3 = r3 - r2
|
||||
r0.<init>(r1, r2, r3)
|
||||
return r0
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.tls.DistinguishedNameParser.escapedAV():java.lang.String");
|
||||
}
|
||||
|
||||
private int getByte(int i) {
|
||||
int i2;
|
||||
int i3;
|
||||
int i4 = i + 1;
|
||||
if (i4 >= this.length) {
|
||||
throw new IllegalStateException("Malformed DN: " + this.dn);
|
||||
}
|
||||
char c = this.chars[i];
|
||||
if (c >= '0' && c <= '9') {
|
||||
i2 = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
i2 = c - 'W';
|
||||
} else {
|
||||
if (c < 'A' || c > 'F') {
|
||||
throw new IllegalStateException("Malformed DN: " + this.dn);
|
||||
}
|
||||
i2 = c - '7';
|
||||
}
|
||||
char c2 = this.chars[i4];
|
||||
if (c2 >= '0' && c2 <= '9') {
|
||||
i3 = c2 - '0';
|
||||
} else if (c2 >= 'a' && c2 <= 'f') {
|
||||
i3 = c2 - 'W';
|
||||
} else {
|
||||
if (c2 < 'A' || c2 > 'F') {
|
||||
throw new IllegalStateException("Malformed DN: " + this.dn);
|
||||
}
|
||||
i3 = c2 - '7';
|
||||
}
|
||||
return (i2 << 4) + i3;
|
||||
}
|
||||
|
||||
private char getEscaped() {
|
||||
this.pos++;
|
||||
int i = this.pos;
|
||||
if (i == this.length) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
char c = this.chars[i];
|
||||
if (c != ' ' && c != '%' && c != '\\' && c != '_' && c != '\"' && c != '#') {
|
||||
switch (c) {
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
break;
|
||||
default:
|
||||
switch (c) {
|
||||
case ';':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
break;
|
||||
default:
|
||||
return getUTF8();
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.chars[this.pos];
|
||||
}
|
||||
|
||||
private char getUTF8() {
|
||||
int i;
|
||||
int i2;
|
||||
int i3 = getByte(this.pos);
|
||||
this.pos++;
|
||||
if (i3 < 128) {
|
||||
return (char) i3;
|
||||
}
|
||||
if (i3 < 192 || i3 > 247) {
|
||||
return '?';
|
||||
}
|
||||
if (i3 <= 223) {
|
||||
i2 = i3 & 31;
|
||||
i = 1;
|
||||
} else if (i3 <= 239) {
|
||||
i = 2;
|
||||
i2 = i3 & 15;
|
||||
} else {
|
||||
i = 3;
|
||||
i2 = i3 & 7;
|
||||
}
|
||||
for (int i4 = 0; i4 < i; i4++) {
|
||||
this.pos++;
|
||||
int i5 = this.pos;
|
||||
if (i5 == this.length || this.chars[i5] != '\\') {
|
||||
return '?';
|
||||
}
|
||||
this.pos = i5 + 1;
|
||||
int i6 = getByte(this.pos);
|
||||
this.pos++;
|
||||
if ((i6 & 192) != 128) {
|
||||
return '?';
|
||||
}
|
||||
i2 = (i2 << 6) + (i6 & 63);
|
||||
}
|
||||
return (char) i2;
|
||||
}
|
||||
|
||||
private String hexAV() {
|
||||
int i = this.pos;
|
||||
if (i + 4 >= this.length) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
this.beg = i;
|
||||
this.pos = i + 1;
|
||||
while (true) {
|
||||
int i2 = this.pos;
|
||||
if (i2 == this.length) {
|
||||
break;
|
||||
}
|
||||
char[] cArr = this.chars;
|
||||
if (cArr[i2] == '+' || cArr[i2] == ',' || cArr[i2] == ';') {
|
||||
break;
|
||||
}
|
||||
if (cArr[i2] == ' ') {
|
||||
this.end = i2;
|
||||
this.pos = i2 + 1;
|
||||
while (true) {
|
||||
int i3 = this.pos;
|
||||
if (i3 >= this.length || this.chars[i3] != ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i3 + 1;
|
||||
}
|
||||
} else {
|
||||
if (cArr[i2] >= 'A' && cArr[i2] <= 'F') {
|
||||
cArr[i2] = (char) (cArr[i2] + ' ');
|
||||
}
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
this.end = this.pos;
|
||||
int i4 = this.end;
|
||||
int i5 = this.beg;
|
||||
int i6 = i4 - i5;
|
||||
if (i6 < 5 || (i6 & 1) == 0) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
byte[] bArr = new byte[i6 / 2];
|
||||
int i7 = i5 + 1;
|
||||
for (int i8 = 0; i8 < bArr.length; i8++) {
|
||||
bArr[i8] = (byte) getByte(i7);
|
||||
i7 += 2;
|
||||
}
|
||||
return new String(this.chars, this.beg, i6);
|
||||
}
|
||||
|
||||
private String nextAT() {
|
||||
while (true) {
|
||||
int i = this.pos;
|
||||
if (i >= this.length || this.chars[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i + 1;
|
||||
}
|
||||
int i2 = this.pos;
|
||||
if (i2 == this.length) {
|
||||
return null;
|
||||
}
|
||||
this.beg = i2;
|
||||
this.pos = i2 + 1;
|
||||
while (true) {
|
||||
int i3 = this.pos;
|
||||
if (i3 >= this.length) {
|
||||
break;
|
||||
}
|
||||
char[] cArr = this.chars;
|
||||
if (cArr[i3] == '=' || cArr[i3] == ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i3 + 1;
|
||||
}
|
||||
int i4 = this.pos;
|
||||
if (i4 >= this.length) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
this.end = i4;
|
||||
if (this.chars[i4] == ' ') {
|
||||
while (true) {
|
||||
int i5 = this.pos;
|
||||
if (i5 >= this.length) {
|
||||
break;
|
||||
}
|
||||
char[] cArr2 = this.chars;
|
||||
if (cArr2[i5] == '=' || cArr2[i5] != ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i5 + 1;
|
||||
}
|
||||
char[] cArr3 = this.chars;
|
||||
int i6 = this.pos;
|
||||
if (cArr3[i6] != '=' || i6 == this.length) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
}
|
||||
this.pos++;
|
||||
while (true) {
|
||||
int i7 = this.pos;
|
||||
if (i7 >= this.length || this.chars[i7] != ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i7 + 1;
|
||||
}
|
||||
int i8 = this.end;
|
||||
int i9 = this.beg;
|
||||
if (i8 - i9 > 4) {
|
||||
char[] cArr4 = this.chars;
|
||||
if (cArr4[i9 + 3] == '.' && (cArr4[i9] == 'O' || cArr4[i9] == 'o')) {
|
||||
char[] cArr5 = this.chars;
|
||||
int i10 = this.beg;
|
||||
if (cArr5[i10 + 1] == 'I' || cArr5[i10 + 1] == 'i') {
|
||||
char[] cArr6 = this.chars;
|
||||
int i11 = this.beg;
|
||||
if (cArr6[i11 + 2] == 'D' || cArr6[i11 + 2] == 'd') {
|
||||
this.beg += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
char[] cArr7 = this.chars;
|
||||
int i12 = this.beg;
|
||||
return new String(cArr7, i12, this.end - i12);
|
||||
}
|
||||
|
||||
private String quotedAV() {
|
||||
this.pos++;
|
||||
this.beg = this.pos;
|
||||
this.end = this.beg;
|
||||
while (true) {
|
||||
int i = this.pos;
|
||||
if (i == this.length) {
|
||||
throw new IllegalStateException("Unexpected end of DN: " + this.dn);
|
||||
}
|
||||
char[] cArr = this.chars;
|
||||
if (cArr[i] == '\"') {
|
||||
this.pos = i + 1;
|
||||
while (true) {
|
||||
int i2 = this.pos;
|
||||
if (i2 >= this.length || this.chars[i2] != ' ') {
|
||||
break;
|
||||
}
|
||||
this.pos = i2 + 1;
|
||||
}
|
||||
char[] cArr2 = this.chars;
|
||||
int i3 = this.beg;
|
||||
return new String(cArr2, i3, this.end - i3);
|
||||
}
|
||||
if (cArr[i] == '\\') {
|
||||
cArr[this.end] = getEscaped();
|
||||
} else {
|
||||
cArr[this.end] = cArr[i];
|
||||
}
|
||||
this.pos++;
|
||||
this.end++;
|
||||
}
|
||||
}
|
||||
|
||||
public String findMostSpecific(String str) {
|
||||
this.pos = 0;
|
||||
this.beg = 0;
|
||||
this.end = 0;
|
||||
this.cur = 0;
|
||||
this.chars = this.dn.toCharArray();
|
||||
String nextAT = nextAT();
|
||||
if (nextAT == null) {
|
||||
return null;
|
||||
}
|
||||
do {
|
||||
int i = this.pos;
|
||||
if (i == this.length) {
|
||||
return null;
|
||||
}
|
||||
char c = this.chars[i];
|
||||
String escapedAV = c != '\"' ? c != '#' ? (c == '+' || c == ',' || c == ';') ? "" : escapedAV() : hexAV() : quotedAV();
|
||||
if (str.equalsIgnoreCase(nextAT)) {
|
||||
return escapedAV;
|
||||
}
|
||||
int i2 = this.pos;
|
||||
if (i2 >= this.length) {
|
||||
return null;
|
||||
}
|
||||
char[] cArr = this.chars;
|
||||
if (cArr[i2] != ',' && cArr[i2] != ';' && cArr[i2] != '+') {
|
||||
throw new IllegalStateException("Malformed DN: " + this.dn);
|
||||
}
|
||||
this.pos++;
|
||||
nextAT = nextAT();
|
||||
} while (nextAT != null);
|
||||
throw new IllegalStateException("Malformed DN: " + this.dn);
|
||||
}
|
||||
}
|
||||
116
sources/okhttp3/internal/tls/OkHostnameVerifier.java
Normal file
116
sources/okhttp3/internal/tls/OkHostnameVerifier.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import okhttp3.internal.Util;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class OkHostnameVerifier implements HostnameVerifier {
|
||||
private static final int ALT_DNS_NAME = 2;
|
||||
private static final int ALT_IPA_NAME = 7;
|
||||
public static final OkHostnameVerifier INSTANCE = new OkHostnameVerifier();
|
||||
|
||||
private OkHostnameVerifier() {
|
||||
}
|
||||
|
||||
public static List<String> allSubjectAltNames(X509Certificate x509Certificate) {
|
||||
List<String> subjectAltNames = getSubjectAltNames(x509Certificate, 7);
|
||||
List<String> subjectAltNames2 = getSubjectAltNames(x509Certificate, 2);
|
||||
ArrayList arrayList = new ArrayList(subjectAltNames.size() + subjectAltNames2.size());
|
||||
arrayList.addAll(subjectAltNames);
|
||||
arrayList.addAll(subjectAltNames2);
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
private static List<String> getSubjectAltNames(X509Certificate x509Certificate, int i) {
|
||||
Integer num;
|
||||
String str;
|
||||
ArrayList arrayList = new ArrayList();
|
||||
try {
|
||||
Collection<List<?>> subjectAlternativeNames = x509Certificate.getSubjectAlternativeNames();
|
||||
if (subjectAlternativeNames == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
for (List<?> list : subjectAlternativeNames) {
|
||||
if (list != null && list.size() >= 2 && (num = (Integer) list.get(0)) != null && num.intValue() == i && (str = (String) list.get(1)) != null) {
|
||||
arrayList.add(str);
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
} catch (CertificateParsingException unused) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifyHostname(String str, X509Certificate x509Certificate) {
|
||||
String lowerCase = str.toLowerCase(Locale.US);
|
||||
Iterator<String> it = getSubjectAltNames(x509Certificate, 2).iterator();
|
||||
while (it.hasNext()) {
|
||||
if (verifyHostname(lowerCase, it.next())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean verifyIpAddress(String str, X509Certificate x509Certificate) {
|
||||
List<String> subjectAltNames = getSubjectAltNames(x509Certificate, 7);
|
||||
int size = subjectAltNames.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (str.equalsIgnoreCase(subjectAltNames.get(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // javax.net.ssl.HostnameVerifier
|
||||
public boolean verify(String str, SSLSession sSLSession) {
|
||||
try {
|
||||
return verify(str, (X509Certificate) sSLSession.getPeerCertificates()[0]);
|
||||
} catch (SSLException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verify(String str, X509Certificate x509Certificate) {
|
||||
if (Util.verifyAsIpAddress(str)) {
|
||||
return verifyIpAddress(str, x509Certificate);
|
||||
}
|
||||
return verifyHostname(str, x509Certificate);
|
||||
}
|
||||
|
||||
public boolean verifyHostname(String str, String str2) {
|
||||
if (str != null && str.length() != 0 && !str.startsWith(".") && !str.endsWith("..") && str2 != null && str2.length() != 0 && !str2.startsWith(".") && !str2.endsWith("..")) {
|
||||
if (!str.endsWith(".")) {
|
||||
str = str + '.';
|
||||
}
|
||||
if (!str2.endsWith(".")) {
|
||||
str2 = str2 + '.';
|
||||
}
|
||||
String lowerCase = str2.toLowerCase(Locale.US);
|
||||
if (!lowerCase.contains("*")) {
|
||||
return str.equals(lowerCase);
|
||||
}
|
||||
if (!lowerCase.startsWith("*.") || lowerCase.indexOf(42, 1) != -1 || str.length() < lowerCase.length() || "*.".equals(lowerCase)) {
|
||||
return false;
|
||||
}
|
||||
String substring = lowerCase.substring(1);
|
||||
if (!str.endsWith(substring)) {
|
||||
return false;
|
||||
}
|
||||
int length = str.length() - substring.length();
|
||||
return length <= 0 || str.lastIndexOf(46, length - 1) == -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
8
sources/okhttp3/internal/tls/TrustRootIndex.java
Normal file
8
sources/okhttp3/internal/tls/TrustRootIndex.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package okhttp3.internal.tls;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface TrustRootIndex {
|
||||
X509Certificate findByIssuerAndSignature(X509Certificate x509Certificate);
|
||||
}
|
||||
555
sources/okhttp3/internal/ws/RealWebSocket.java
Normal file
555
sources/okhttp3/internal/ws/RealWebSocket.java
Normal file
@@ -0,0 +1,555 @@
|
||||
package okhttp3.internal.ws;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.EventListener;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.connection.StreamAllocation;
|
||||
import okhttp3.internal.ws.WebSocketReader;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
private static final long CANCEL_AFTER_CLOSE_MILLIS = 60000;
|
||||
private static final long MAX_QUEUE_SIZE = 16777216;
|
||||
private static final List<Protocol> ONLY_HTTP1 = Collections.singletonList(Protocol.HTTP_1_1);
|
||||
private boolean awaitingPong;
|
||||
private Call call;
|
||||
private ScheduledFuture<?> cancelFuture;
|
||||
private boolean enqueuedClose;
|
||||
private ScheduledExecutorService executor;
|
||||
private boolean failed;
|
||||
private final String key;
|
||||
final WebSocketListener listener;
|
||||
private final Request originalRequest;
|
||||
private final long pingIntervalMillis;
|
||||
private long queueSize;
|
||||
private final Random random;
|
||||
private WebSocketReader reader;
|
||||
private String receivedCloseReason;
|
||||
private int receivedPingCount;
|
||||
private int receivedPongCount;
|
||||
private int sentPingCount;
|
||||
private Streams streams;
|
||||
private WebSocketWriter writer;
|
||||
private final Runnable writerRunnable;
|
||||
private final ArrayDeque<ByteString> pongQueue = new ArrayDeque<>();
|
||||
private final ArrayDeque<Object> messageAndCloseQueue = new ArrayDeque<>();
|
||||
private int receivedCloseCode = -1;
|
||||
|
||||
final class CancelRunnable implements Runnable {
|
||||
CancelRunnable() {
|
||||
}
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
RealWebSocket.this.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
static final class Close {
|
||||
final long cancelAfterCloseMillis;
|
||||
final int code;
|
||||
final ByteString reason;
|
||||
|
||||
Close(int i, ByteString byteString, long j) {
|
||||
this.code = i;
|
||||
this.reason = byteString;
|
||||
this.cancelAfterCloseMillis = j;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Message {
|
||||
final ByteString data;
|
||||
final int formatOpcode;
|
||||
|
||||
Message(int i, ByteString byteString) {
|
||||
this.formatOpcode = i;
|
||||
this.data = byteString;
|
||||
}
|
||||
}
|
||||
|
||||
private final class PingRunnable implements Runnable {
|
||||
PingRunnable() {
|
||||
}
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
RealWebSocket.this.writePingFrame();
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Streams implements Closeable {
|
||||
public final boolean client;
|
||||
public final BufferedSink sink;
|
||||
public final BufferedSource source;
|
||||
|
||||
public Streams(boolean z, BufferedSource bufferedSource, BufferedSink bufferedSink) {
|
||||
this.client = z;
|
||||
this.source = bufferedSource;
|
||||
this.sink = bufferedSink;
|
||||
}
|
||||
}
|
||||
|
||||
public RealWebSocket(Request request, WebSocketListener webSocketListener, Random random, long j) {
|
||||
if (!"GET".equals(request.method())) {
|
||||
throw new IllegalArgumentException("Request must be GET: " + request.method());
|
||||
}
|
||||
this.originalRequest = request;
|
||||
this.listener = webSocketListener;
|
||||
this.random = random;
|
||||
this.pingIntervalMillis = j;
|
||||
byte[] bArr = new byte[16];
|
||||
random.nextBytes(bArr);
|
||||
this.key = ByteString.of(bArr).base64();
|
||||
this.writerRunnable = new Runnable() { // from class: okhttp3.internal.ws.RealWebSocket.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
do {
|
||||
try {
|
||||
} catch (IOException e) {
|
||||
RealWebSocket.this.failWebSocket(e, null);
|
||||
return;
|
||||
}
|
||||
} while (RealWebSocket.this.writeOneFrame());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void runWriter() {
|
||||
ScheduledExecutorService scheduledExecutorService = this.executor;
|
||||
if (scheduledExecutorService != null) {
|
||||
scheduledExecutorService.execute(this.writerRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
void awaitTermination(int i, TimeUnit timeUnit) throws InterruptedException {
|
||||
this.executor.awaitTermination(i, timeUnit);
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public void cancel() {
|
||||
this.call.cancel();
|
||||
}
|
||||
|
||||
void checkResponse(Response response) throws ProtocolException {
|
||||
if (response.code() != 101) {
|
||||
throw new ProtocolException("Expected HTTP 101 response but was '" + response.code() + " " + response.message() + "'");
|
||||
}
|
||||
String header = response.header("Connection");
|
||||
if (!"Upgrade".equalsIgnoreCase(header)) {
|
||||
throw new ProtocolException("Expected 'Connection' header value 'Upgrade' but was '" + header + "'");
|
||||
}
|
||||
String header2 = response.header("Upgrade");
|
||||
if (!"websocket".equalsIgnoreCase(header2)) {
|
||||
throw new ProtocolException("Expected 'Upgrade' header value 'websocket' but was '" + header2 + "'");
|
||||
}
|
||||
String header3 = response.header("Sec-WebSocket-Accept");
|
||||
String base64 = ByteString.encodeUtf8(this.key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").sha1().base64();
|
||||
if (base64.equals(header3)) {
|
||||
return;
|
||||
}
|
||||
throw new ProtocolException("Expected 'Sec-WebSocket-Accept' header value '" + base64 + "' but was '" + header3 + "'");
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public boolean close(int i, String str) {
|
||||
return close(i, str, CANCEL_AFTER_CLOSE_MILLIS);
|
||||
}
|
||||
|
||||
public void connect(OkHttpClient okHttpClient) {
|
||||
OkHttpClient build = okHttpClient.newBuilder().eventListener(EventListener.NONE).protocols(ONLY_HTTP1).build();
|
||||
final Request build2 = this.originalRequest.newBuilder().header("Upgrade", "websocket").header("Connection", "Upgrade").header("Sec-WebSocket-Key", this.key).header("Sec-WebSocket-Version", "13").build();
|
||||
this.call = Internal.instance.newWebSocketCall(build, build2);
|
||||
this.call.enqueue(new Callback() { // from class: okhttp3.internal.ws.RealWebSocket.2
|
||||
@Override // okhttp3.Callback
|
||||
public void onFailure(Call call, IOException iOException) {
|
||||
RealWebSocket.this.failWebSocket(iOException, null);
|
||||
}
|
||||
|
||||
@Override // okhttp3.Callback
|
||||
public void onResponse(Call call, Response response) {
|
||||
try {
|
||||
RealWebSocket.this.checkResponse(response);
|
||||
StreamAllocation streamAllocation = Internal.instance.streamAllocation(call);
|
||||
streamAllocation.noNewStreams();
|
||||
Streams newWebSocketStreams = streamAllocation.connection().newWebSocketStreams(streamAllocation);
|
||||
try {
|
||||
RealWebSocket.this.listener.onOpen(RealWebSocket.this, response);
|
||||
RealWebSocket.this.initReaderAndWriter("OkHttp WebSocket " + build2.url().redact(), newWebSocketStreams);
|
||||
streamAllocation.connection().socket().setSoTimeout(0);
|
||||
RealWebSocket.this.loopReader();
|
||||
} catch (Exception e) {
|
||||
RealWebSocket.this.failWebSocket(e, null);
|
||||
}
|
||||
} catch (ProtocolException e2) {
|
||||
RealWebSocket.this.failWebSocket(e2, response);
|
||||
Util.closeQuietly(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void failWebSocket(Exception exc, Response response) {
|
||||
synchronized (this) {
|
||||
if (this.failed) {
|
||||
return;
|
||||
}
|
||||
this.failed = true;
|
||||
Streams streams = this.streams;
|
||||
this.streams = null;
|
||||
if (this.cancelFuture != null) {
|
||||
this.cancelFuture.cancel(false);
|
||||
}
|
||||
if (this.executor != null) {
|
||||
this.executor.shutdown();
|
||||
}
|
||||
try {
|
||||
this.listener.onFailure(this, exc, response);
|
||||
} finally {
|
||||
Util.closeQuietly(streams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initReaderAndWriter(String str, Streams streams) throws IOException {
|
||||
synchronized (this) {
|
||||
this.streams = streams;
|
||||
this.writer = new WebSocketWriter(streams.client, streams.sink, this.random);
|
||||
this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(str, false));
|
||||
if (this.pingIntervalMillis != 0) {
|
||||
this.executor.scheduleAtFixedRate(new PingRunnable(), this.pingIntervalMillis, this.pingIntervalMillis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
if (!this.messageAndCloseQueue.isEmpty()) {
|
||||
runWriter();
|
||||
}
|
||||
}
|
||||
this.reader = new WebSocketReader(streams.client, streams.source, this);
|
||||
}
|
||||
|
||||
public void loopReader() throws IOException {
|
||||
while (this.receivedCloseCode == -1) {
|
||||
this.reader.processNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.ws.WebSocketReader.FrameCallback
|
||||
public void onReadClose(int i, String str) {
|
||||
Streams streams;
|
||||
if (i == -1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (this.receivedCloseCode != -1) {
|
||||
throw new IllegalStateException("already closed");
|
||||
}
|
||||
this.receivedCloseCode = i;
|
||||
this.receivedCloseReason = str;
|
||||
if (this.enqueuedClose && this.messageAndCloseQueue.isEmpty()) {
|
||||
streams = this.streams;
|
||||
this.streams = null;
|
||||
if (this.cancelFuture != null) {
|
||||
this.cancelFuture.cancel(false);
|
||||
}
|
||||
this.executor.shutdown();
|
||||
} else {
|
||||
streams = null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.listener.onClosing(this, i, str);
|
||||
if (streams != null) {
|
||||
this.listener.onClosed(this, i, str);
|
||||
}
|
||||
} finally {
|
||||
Util.closeQuietly(streams);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.ws.WebSocketReader.FrameCallback
|
||||
public void onReadMessage(String str) throws IOException {
|
||||
this.listener.onMessage(this, str);
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.ws.WebSocketReader.FrameCallback
|
||||
public synchronized void onReadPing(ByteString byteString) {
|
||||
if (!this.failed && (!this.enqueuedClose || !this.messageAndCloseQueue.isEmpty())) {
|
||||
this.pongQueue.add(byteString);
|
||||
runWriter();
|
||||
this.receivedPingCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.ws.WebSocketReader.FrameCallback
|
||||
public synchronized void onReadPong(ByteString byteString) {
|
||||
this.receivedPongCount++;
|
||||
this.awaitingPong = false;
|
||||
}
|
||||
|
||||
synchronized boolean pong(ByteString byteString) {
|
||||
if (!this.failed && (!this.enqueuedClose || !this.messageAndCloseQueue.isEmpty())) {
|
||||
this.pongQueue.add(byteString);
|
||||
runWriter();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean processNextFrame() throws IOException {
|
||||
try {
|
||||
this.reader.processNextFrame();
|
||||
return this.receivedCloseCode == -1;
|
||||
} catch (Exception e) {
|
||||
failWebSocket(e, null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public synchronized long queueSize() {
|
||||
return this.queueSize;
|
||||
}
|
||||
|
||||
synchronized int receivedPingCount() {
|
||||
return this.receivedPingCount;
|
||||
}
|
||||
|
||||
synchronized int receivedPongCount() {
|
||||
return this.receivedPongCount;
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public Request request() {
|
||||
return this.originalRequest;
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public boolean send(String str) {
|
||||
if (str != null) {
|
||||
return send(ByteString.encodeUtf8(str), 1);
|
||||
}
|
||||
throw new NullPointerException("text == null");
|
||||
}
|
||||
|
||||
synchronized int sentPingCount() {
|
||||
return this.sentPingCount;
|
||||
}
|
||||
|
||||
void tearDown() throws InterruptedException {
|
||||
ScheduledFuture<?> scheduledFuture = this.cancelFuture;
|
||||
if (scheduledFuture != null) {
|
||||
scheduledFuture.cancel(false);
|
||||
}
|
||||
this.executor.shutdown();
|
||||
this.executor.awaitTermination(10L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/* JADX WARN: Removed duplicated region for block: B:18:0x0052 A[Catch: all -> 0x00a5, TRY_ENTER, TryCatch #1 {all -> 0x00a5, blocks: (B:18:0x0052, B:21:0x0056, B:23:0x005a, B:24:0x0076, B:32:0x0085, B:33:0x0086, B:35:0x008a, B:37:0x0095, B:38:0x009f, B:39:0x00a4, B:26:0x0077, B:27:0x0081), top: B:16:0x0050 }] */
|
||||
/* JADX WARN: Removed duplicated region for block: B:21:0x0056 A[Catch: all -> 0x00a5, TryCatch #1 {all -> 0x00a5, blocks: (B:18:0x0052, B:21:0x0056, B:23:0x005a, B:24:0x0076, B:32:0x0085, B:33:0x0086, B:35:0x008a, B:37:0x0095, B:38:0x009f, B:39:0x00a4, B:26:0x0077, B:27:0x0081), top: B:16:0x0050 }] */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
boolean writeOneFrame() throws java.io.IOException {
|
||||
/*
|
||||
r11 = this;
|
||||
monitor-enter(r11)
|
||||
boolean r0 = r11.failed // Catch: java.lang.Throwable -> Laa
|
||||
r1 = 0
|
||||
if (r0 == 0) goto L8
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> Laa
|
||||
return r1
|
||||
L8:
|
||||
okhttp3.internal.ws.WebSocketWriter r0 = r11.writer // Catch: java.lang.Throwable -> Laa
|
||||
java.util.ArrayDeque<okio.ByteString> r2 = r11.pongQueue // Catch: java.lang.Throwable -> Laa
|
||||
java.lang.Object r2 = r2.poll() // Catch: java.lang.Throwable -> Laa
|
||||
okio.ByteString r2 = (okio.ByteString) r2 // Catch: java.lang.Throwable -> Laa
|
||||
r3 = -1
|
||||
r4 = 0
|
||||
if (r2 != 0) goto L4c
|
||||
java.util.ArrayDeque<java.lang.Object> r5 = r11.messageAndCloseQueue // Catch: java.lang.Throwable -> Laa
|
||||
java.lang.Object r5 = r5.poll() // Catch: java.lang.Throwable -> Laa
|
||||
boolean r6 = r5 instanceof okhttp3.internal.ws.RealWebSocket.Close // Catch: java.lang.Throwable -> Laa
|
||||
if (r6 == 0) goto L46
|
||||
int r1 = r11.receivedCloseCode // Catch: java.lang.Throwable -> Laa
|
||||
java.lang.String r6 = r11.receivedCloseReason // Catch: java.lang.Throwable -> Laa
|
||||
if (r1 == r3) goto L31
|
||||
okhttp3.internal.ws.RealWebSocket$Streams r3 = r11.streams // Catch: java.lang.Throwable -> Laa
|
||||
r11.streams = r4 // Catch: java.lang.Throwable -> Laa
|
||||
java.util.concurrent.ScheduledExecutorService r4 = r11.executor // Catch: java.lang.Throwable -> Laa
|
||||
r4.shutdown() // Catch: java.lang.Throwable -> Laa
|
||||
r4 = r3
|
||||
goto L4f
|
||||
L31:
|
||||
java.util.concurrent.ScheduledExecutorService r3 = r11.executor // Catch: java.lang.Throwable -> Laa
|
||||
okhttp3.internal.ws.RealWebSocket$CancelRunnable r7 = new okhttp3.internal.ws.RealWebSocket$CancelRunnable // Catch: java.lang.Throwable -> Laa
|
||||
r7.<init>() // Catch: java.lang.Throwable -> Laa
|
||||
r8 = r5
|
||||
okhttp3.internal.ws.RealWebSocket$Close r8 = (okhttp3.internal.ws.RealWebSocket.Close) r8 // Catch: java.lang.Throwable -> Laa
|
||||
long r8 = r8.cancelAfterCloseMillis // Catch: java.lang.Throwable -> Laa
|
||||
java.util.concurrent.TimeUnit r10 = java.util.concurrent.TimeUnit.MILLISECONDS // Catch: java.lang.Throwable -> Laa
|
||||
java.util.concurrent.ScheduledFuture r3 = r3.schedule(r7, r8, r10) // Catch: java.lang.Throwable -> Laa
|
||||
r11.cancelFuture = r3 // Catch: java.lang.Throwable -> Laa
|
||||
goto L4f
|
||||
L46:
|
||||
if (r5 != 0) goto L4a
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> Laa
|
||||
return r1
|
||||
L4a:
|
||||
r6 = r4
|
||||
goto L4e
|
||||
L4c:
|
||||
r5 = r4
|
||||
r6 = r5
|
||||
L4e:
|
||||
r1 = -1
|
||||
L4f:
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> Laa
|
||||
if (r2 == 0) goto L56
|
||||
r0.writePong(r2) // Catch: java.lang.Throwable -> La5
|
||||
goto L9a
|
||||
L56:
|
||||
boolean r2 = r5 instanceof okhttp3.internal.ws.RealWebSocket.Message // Catch: java.lang.Throwable -> La5
|
||||
if (r2 == 0) goto L86
|
||||
r1 = r5
|
||||
okhttp3.internal.ws.RealWebSocket$Message r1 = (okhttp3.internal.ws.RealWebSocket.Message) r1 // Catch: java.lang.Throwable -> La5
|
||||
okio.ByteString r1 = r1.data // Catch: java.lang.Throwable -> La5
|
||||
okhttp3.internal.ws.RealWebSocket$Message r5 = (okhttp3.internal.ws.RealWebSocket.Message) r5 // Catch: java.lang.Throwable -> La5
|
||||
int r2 = r5.formatOpcode // Catch: java.lang.Throwable -> La5
|
||||
int r3 = r1.size() // Catch: java.lang.Throwable -> La5
|
||||
long r5 = (long) r3 // Catch: java.lang.Throwable -> La5
|
||||
okio.Sink r0 = r0.newMessageSink(r2, r5) // Catch: java.lang.Throwable -> La5
|
||||
okio.BufferedSink r0 = okio.Okio.buffer(r0) // Catch: java.lang.Throwable -> La5
|
||||
r0.write(r1) // Catch: java.lang.Throwable -> La5
|
||||
r0.close() // Catch: java.lang.Throwable -> La5
|
||||
monitor-enter(r11) // Catch: java.lang.Throwable -> La5
|
||||
long r2 = r11.queueSize // Catch: java.lang.Throwable -> L83
|
||||
int r0 = r1.size() // Catch: java.lang.Throwable -> L83
|
||||
long r0 = (long) r0 // Catch: java.lang.Throwable -> L83
|
||||
long r2 = r2 - r0
|
||||
r11.queueSize = r2 // Catch: java.lang.Throwable -> L83
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> L83
|
||||
goto L9a
|
||||
L83:
|
||||
r0 = move-exception
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> L83
|
||||
throw r0 // Catch: java.lang.Throwable -> La5
|
||||
L86:
|
||||
boolean r2 = r5 instanceof okhttp3.internal.ws.RealWebSocket.Close // Catch: java.lang.Throwable -> La5
|
||||
if (r2 == 0) goto L9f
|
||||
okhttp3.internal.ws.RealWebSocket$Close r5 = (okhttp3.internal.ws.RealWebSocket.Close) r5 // Catch: java.lang.Throwable -> La5
|
||||
int r2 = r5.code // Catch: java.lang.Throwable -> La5
|
||||
okio.ByteString r3 = r5.reason // Catch: java.lang.Throwable -> La5
|
||||
r0.writeClose(r2, r3) // Catch: java.lang.Throwable -> La5
|
||||
if (r4 == 0) goto L9a
|
||||
okhttp3.WebSocketListener r0 = r11.listener // Catch: java.lang.Throwable -> La5
|
||||
r0.onClosed(r11, r1, r6) // Catch: java.lang.Throwable -> La5
|
||||
L9a:
|
||||
r0 = 1
|
||||
okhttp3.internal.Util.closeQuietly(r4)
|
||||
return r0
|
||||
L9f:
|
||||
java.lang.AssertionError r0 = new java.lang.AssertionError // Catch: java.lang.Throwable -> La5
|
||||
r0.<init>() // Catch: java.lang.Throwable -> La5
|
||||
throw r0 // Catch: java.lang.Throwable -> La5
|
||||
La5:
|
||||
r0 = move-exception
|
||||
okhttp3.internal.Util.closeQuietly(r4)
|
||||
throw r0
|
||||
Laa:
|
||||
r0 = move-exception
|
||||
monitor-exit(r11) // Catch: java.lang.Throwable -> Laa
|
||||
throw r0
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.ws.RealWebSocket.writeOneFrame():boolean");
|
||||
}
|
||||
|
||||
void writePingFrame() {
|
||||
synchronized (this) {
|
||||
if (this.failed) {
|
||||
return;
|
||||
}
|
||||
WebSocketWriter webSocketWriter = this.writer;
|
||||
int i = this.awaitingPong ? this.sentPingCount : -1;
|
||||
this.sentPingCount++;
|
||||
this.awaitingPong = true;
|
||||
if (i == -1) {
|
||||
try {
|
||||
webSocketWriter.writePing(ByteString.EMPTY);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
failWebSocket(e, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
failWebSocket(new SocketTimeoutException("sent ping but didn't receive pong within " + this.pingIntervalMillis + "ms (after " + (i - 1) + " successful ping/pongs)"), null);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized boolean close(int i, String str, long j) {
|
||||
WebSocketProtocol.validateCloseCode(i);
|
||||
ByteString byteString = null;
|
||||
if (str != null) {
|
||||
byteString = ByteString.encodeUtf8(str);
|
||||
if (byteString.size() > 123) {
|
||||
throw new IllegalArgumentException("reason.size() > 123: " + str);
|
||||
}
|
||||
}
|
||||
if (!this.failed && !this.enqueuedClose) {
|
||||
this.enqueuedClose = true;
|
||||
this.messageAndCloseQueue.add(new Close(i, byteString, j));
|
||||
runWriter();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // okhttp3.internal.ws.WebSocketReader.FrameCallback
|
||||
public void onReadMessage(ByteString byteString) throws IOException {
|
||||
this.listener.onMessage(this, byteString);
|
||||
}
|
||||
|
||||
@Override // okhttp3.WebSocket
|
||||
public boolean send(ByteString byteString) {
|
||||
if (byteString != null) {
|
||||
return send(byteString, 2);
|
||||
}
|
||||
throw new NullPointerException("bytes == null");
|
||||
}
|
||||
|
||||
private synchronized boolean send(ByteString byteString, int i) {
|
||||
if (!this.failed && !this.enqueuedClose) {
|
||||
if (this.queueSize + byteString.size() > MAX_QUEUE_SIZE) {
|
||||
close(1001, null);
|
||||
return false;
|
||||
}
|
||||
this.queueSize += byteString.size();
|
||||
this.messageAndCloseQueue.add(new Message(i, byteString));
|
||||
runWriter();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
71
sources/okhttp3/internal/ws/WebSocketProtocol.java
Normal file
71
sources/okhttp3/internal/ws/WebSocketProtocol.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package okhttp3.internal.ws;
|
||||
|
||||
import okio.Buffer;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class WebSocketProtocol {
|
||||
static final String ACCEPT_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
static final int B0_FLAG_FIN = 128;
|
||||
static final int B0_FLAG_RSV1 = 64;
|
||||
static final int B0_FLAG_RSV2 = 32;
|
||||
static final int B0_FLAG_RSV3 = 16;
|
||||
static final int B0_MASK_OPCODE = 15;
|
||||
static final int B1_FLAG_MASK = 128;
|
||||
static final int B1_MASK_LENGTH = 127;
|
||||
static final int CLOSE_CLIENT_GOING_AWAY = 1001;
|
||||
static final long CLOSE_MESSAGE_MAX = 123;
|
||||
static final int CLOSE_NO_STATUS_CODE = 1005;
|
||||
static final int OPCODE_BINARY = 2;
|
||||
static final int OPCODE_CONTINUATION = 0;
|
||||
static final int OPCODE_CONTROL_CLOSE = 8;
|
||||
static final int OPCODE_CONTROL_PING = 9;
|
||||
static final int OPCODE_CONTROL_PONG = 10;
|
||||
static final int OPCODE_FLAG_CONTROL = 8;
|
||||
static final int OPCODE_TEXT = 1;
|
||||
static final long PAYLOAD_BYTE_MAX = 125;
|
||||
static final int PAYLOAD_LONG = 127;
|
||||
static final int PAYLOAD_SHORT = 126;
|
||||
static final long PAYLOAD_SHORT_MAX = 65535;
|
||||
|
||||
private WebSocketProtocol() {
|
||||
throw new AssertionError("No instances.");
|
||||
}
|
||||
|
||||
public static String acceptHeader(String str) {
|
||||
return ByteString.encodeUtf8(str + ACCEPT_MAGIC).sha1().base64();
|
||||
}
|
||||
|
||||
static String closeCodeExceptionMessage(int i) {
|
||||
if (i < 1000 || i >= 5000) {
|
||||
return "Code must be in range [1000,5000): " + i;
|
||||
}
|
||||
if ((i < 1004 || i > 1006) && (i < 1012 || i > 2999)) {
|
||||
return null;
|
||||
}
|
||||
return "Code " + i + " is reserved and may not be used.";
|
||||
}
|
||||
|
||||
static void toggleMask(Buffer.UnsafeCursor unsafeCursor, byte[] bArr) {
|
||||
int length = bArr.length;
|
||||
int i = 0;
|
||||
do {
|
||||
byte[] bArr2 = unsafeCursor.data;
|
||||
int i2 = unsafeCursor.start;
|
||||
int i3 = unsafeCursor.end;
|
||||
while (i2 < i3) {
|
||||
int i4 = i % length;
|
||||
bArr2[i2] = (byte) (bArr2[i2] ^ bArr[i4]);
|
||||
i2++;
|
||||
i = i4 + 1;
|
||||
}
|
||||
} while (unsafeCursor.next() != -1);
|
||||
}
|
||||
|
||||
static void validateCloseCode(int i) {
|
||||
String closeCodeExceptionMessage = closeCodeExceptionMessage(i);
|
||||
if (closeCodeExceptionMessage != null) {
|
||||
throw new IllegalArgumentException(closeCodeExceptionMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
199
sources/okhttp3/internal/ws/WebSocketReader.java
Normal file
199
sources/okhttp3/internal/ws/WebSocketReader.java
Normal file
@@ -0,0 +1,199 @@
|
||||
package okhttp3.internal.ws;
|
||||
|
||||
import com.ubtrobot.jimu.robotapi.PeripheralType;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
import okio.ByteString;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class WebSocketReader {
|
||||
boolean closed;
|
||||
final FrameCallback frameCallback;
|
||||
long frameLength;
|
||||
final boolean isClient;
|
||||
boolean isControlFrame;
|
||||
boolean isFinalFrame;
|
||||
private final Buffer.UnsafeCursor maskCursor;
|
||||
private final byte[] maskKey;
|
||||
int opcode;
|
||||
final BufferedSource source;
|
||||
private final Buffer controlFrameBuffer = new Buffer();
|
||||
private final Buffer messageFrameBuffer = new Buffer();
|
||||
|
||||
public interface FrameCallback {
|
||||
void onReadClose(int i, String str);
|
||||
|
||||
void onReadMessage(String str) throws IOException;
|
||||
|
||||
void onReadMessage(ByteString byteString) throws IOException;
|
||||
|
||||
void onReadPing(ByteString byteString);
|
||||
|
||||
void onReadPong(ByteString byteString);
|
||||
}
|
||||
|
||||
WebSocketReader(boolean z, BufferedSource bufferedSource, FrameCallback frameCallback) {
|
||||
if (bufferedSource == null) {
|
||||
throw new NullPointerException("source == null");
|
||||
}
|
||||
if (frameCallback == null) {
|
||||
throw new NullPointerException("frameCallback == null");
|
||||
}
|
||||
this.isClient = z;
|
||||
this.source = bufferedSource;
|
||||
this.frameCallback = frameCallback;
|
||||
this.maskKey = z ? null : new byte[4];
|
||||
this.maskCursor = z ? null : new Buffer.UnsafeCursor();
|
||||
}
|
||||
|
||||
private void readControlFrame() throws IOException {
|
||||
String str;
|
||||
long j = this.frameLength;
|
||||
if (j > 0) {
|
||||
this.source.readFully(this.controlFrameBuffer, j);
|
||||
if (!this.isClient) {
|
||||
this.controlFrameBuffer.readAndWriteUnsafe(this.maskCursor);
|
||||
this.maskCursor.seek(0L);
|
||||
WebSocketProtocol.toggleMask(this.maskCursor, this.maskKey);
|
||||
this.maskCursor.close();
|
||||
}
|
||||
}
|
||||
switch (this.opcode) {
|
||||
case 8:
|
||||
short s = 1005;
|
||||
long size = this.controlFrameBuffer.size();
|
||||
if (size == 1) {
|
||||
throw new ProtocolException("Malformed close payload length of 1.");
|
||||
}
|
||||
if (size != 0) {
|
||||
s = this.controlFrameBuffer.readShort();
|
||||
str = this.controlFrameBuffer.readUtf8();
|
||||
String closeCodeExceptionMessage = WebSocketProtocol.closeCodeExceptionMessage(s);
|
||||
if (closeCodeExceptionMessage != null) {
|
||||
throw new ProtocolException(closeCodeExceptionMessage);
|
||||
}
|
||||
} else {
|
||||
str = "";
|
||||
}
|
||||
this.frameCallback.onReadClose(s, str);
|
||||
this.closed = true;
|
||||
return;
|
||||
case 9:
|
||||
this.frameCallback.onReadPing(this.controlFrameBuffer.readByteString());
|
||||
return;
|
||||
case 10:
|
||||
this.frameCallback.onReadPong(this.controlFrameBuffer.readByteString());
|
||||
return;
|
||||
default:
|
||||
throw new ProtocolException("Unknown control opcode: " + Integer.toHexString(this.opcode));
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX WARN: Finally extract failed */
|
||||
private void readHeader() throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
long timeoutNanos = this.source.timeout().timeoutNanos();
|
||||
this.source.timeout().clearTimeout();
|
||||
try {
|
||||
int readByte = this.source.readByte() & 255;
|
||||
this.source.timeout().timeout(timeoutNanos, TimeUnit.NANOSECONDS);
|
||||
this.opcode = readByte & 15;
|
||||
this.isFinalFrame = (readByte & PeripheralType.SERVO) != 0;
|
||||
this.isControlFrame = (readByte & 8) != 0;
|
||||
if (this.isControlFrame && !this.isFinalFrame) {
|
||||
throw new ProtocolException("Control frames must be final.");
|
||||
}
|
||||
boolean z = (readByte & 64) != 0;
|
||||
boolean z2 = (readByte & 32) != 0;
|
||||
boolean z3 = (readByte & 16) != 0;
|
||||
if (z || z2 || z3) {
|
||||
throw new ProtocolException("Reserved flags are unsupported.");
|
||||
}
|
||||
boolean z4 = ((this.source.readByte() & 255) & PeripheralType.SERVO) != 0;
|
||||
boolean z5 = this.isClient;
|
||||
if (z4 == z5) {
|
||||
throw new ProtocolException(z5 ? "Server-sent frames must not be masked." : "Client-sent frames must be masked.");
|
||||
}
|
||||
this.frameLength = r0 & 127;
|
||||
long j = this.frameLength;
|
||||
if (j == 126) {
|
||||
this.frameLength = this.source.readShort() & 65535;
|
||||
} else if (j == 127) {
|
||||
this.frameLength = this.source.readLong();
|
||||
if (this.frameLength < 0) {
|
||||
throw new ProtocolException("Frame length 0x" + Long.toHexString(this.frameLength) + " > 0x7FFFFFFFFFFFFFFF");
|
||||
}
|
||||
}
|
||||
if (this.isControlFrame && this.frameLength > 125) {
|
||||
throw new ProtocolException("Control frame must be less than 125B.");
|
||||
}
|
||||
if (z4) {
|
||||
this.source.readFully(this.maskKey);
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
this.source.timeout().timeout(timeoutNanos, TimeUnit.NANOSECONDS);
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
private void readMessage() throws IOException {
|
||||
while (!this.closed) {
|
||||
long j = this.frameLength;
|
||||
if (j > 0) {
|
||||
this.source.readFully(this.messageFrameBuffer, j);
|
||||
if (!this.isClient) {
|
||||
this.messageFrameBuffer.readAndWriteUnsafe(this.maskCursor);
|
||||
this.maskCursor.seek(this.messageFrameBuffer.size() - this.frameLength);
|
||||
WebSocketProtocol.toggleMask(this.maskCursor, this.maskKey);
|
||||
this.maskCursor.close();
|
||||
}
|
||||
}
|
||||
if (this.isFinalFrame) {
|
||||
return;
|
||||
}
|
||||
readUntilNonControlFrame();
|
||||
if (this.opcode != 0) {
|
||||
throw new ProtocolException("Expected continuation opcode. Got: " + Integer.toHexString(this.opcode));
|
||||
}
|
||||
}
|
||||
throw new IOException("closed");
|
||||
}
|
||||
|
||||
private void readMessageFrame() throws IOException {
|
||||
int i = this.opcode;
|
||||
if (i != 1 && i != 2) {
|
||||
throw new ProtocolException("Unknown opcode: " + Integer.toHexString(i));
|
||||
}
|
||||
readMessage();
|
||||
if (i == 1) {
|
||||
this.frameCallback.onReadMessage(this.messageFrameBuffer.readUtf8());
|
||||
} else {
|
||||
this.frameCallback.onReadMessage(this.messageFrameBuffer.readByteString());
|
||||
}
|
||||
}
|
||||
|
||||
private void readUntilNonControlFrame() throws IOException {
|
||||
while (!this.closed) {
|
||||
readHeader();
|
||||
if (!this.isControlFrame) {
|
||||
return;
|
||||
} else {
|
||||
readControlFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processNextFrame() throws IOException {
|
||||
readHeader();
|
||||
if (this.isControlFrame) {
|
||||
readControlFrame();
|
||||
} else {
|
||||
readMessageFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
198
sources/okhttp3/internal/ws/WebSocketWriter.java
Normal file
198
sources/okhttp3/internal/ws/WebSocketWriter.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package okhttp3.internal.ws;
|
||||
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import com.ubtrobot.jimu.robotapi.PeripheralType;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.ByteString;
|
||||
import okio.Sink;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
final class WebSocketWriter {
|
||||
boolean activeWriter;
|
||||
final Buffer buffer = new Buffer();
|
||||
final FrameSink frameSink = new FrameSink();
|
||||
final boolean isClient;
|
||||
private final Buffer.UnsafeCursor maskCursor;
|
||||
private final byte[] maskKey;
|
||||
final Random random;
|
||||
final BufferedSink sink;
|
||||
final Buffer sinkBuffer;
|
||||
boolean writerClosed;
|
||||
|
||||
final class FrameSink implements Sink {
|
||||
boolean closed;
|
||||
long contentLength;
|
||||
int formatOpcode;
|
||||
boolean isFirstFrame;
|
||||
|
||||
FrameSink() {
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
WebSocketWriter webSocketWriter = WebSocketWriter.this;
|
||||
webSocketWriter.writeMessageFrame(this.formatOpcode, webSocketWriter.buffer.size(), this.isFirstFrame, true);
|
||||
this.closed = true;
|
||||
WebSocketWriter.this.activeWriter = false;
|
||||
}
|
||||
|
||||
@Override // okio.Sink, java.io.Flushable
|
||||
public void flush() throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
WebSocketWriter webSocketWriter = WebSocketWriter.this;
|
||||
webSocketWriter.writeMessageFrame(this.formatOpcode, webSocketWriter.buffer.size(), this.isFirstFrame, false);
|
||||
this.isFirstFrame = false;
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public Timeout timeout() {
|
||||
return WebSocketWriter.this.sink.timeout();
|
||||
}
|
||||
|
||||
@Override // okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
if (this.closed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
WebSocketWriter.this.buffer.write(buffer, j);
|
||||
boolean z = this.isFirstFrame && this.contentLength != -1 && WebSocketWriter.this.buffer.size() > this.contentLength - PlaybackStateCompat.ACTION_PLAY_FROM_URI;
|
||||
long completeSegmentByteCount = WebSocketWriter.this.buffer.completeSegmentByteCount();
|
||||
if (completeSegmentByteCount <= 0 || z) {
|
||||
return;
|
||||
}
|
||||
WebSocketWriter.this.writeMessageFrame(this.formatOpcode, completeSegmentByteCount, this.isFirstFrame, false);
|
||||
this.isFirstFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketWriter(boolean z, BufferedSink bufferedSink, Random random) {
|
||||
if (bufferedSink == null) {
|
||||
throw new NullPointerException("sink == null");
|
||||
}
|
||||
if (random == null) {
|
||||
throw new NullPointerException("random == null");
|
||||
}
|
||||
this.isClient = z;
|
||||
this.sink = bufferedSink;
|
||||
this.sinkBuffer = bufferedSink.buffer();
|
||||
this.random = random;
|
||||
this.maskKey = z ? new byte[4] : null;
|
||||
this.maskCursor = z ? new Buffer.UnsafeCursor() : null;
|
||||
}
|
||||
|
||||
private void writeControlFrame(int i, ByteString byteString) throws IOException {
|
||||
if (this.writerClosed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
int size = byteString.size();
|
||||
if (size > 125) {
|
||||
throw new IllegalArgumentException("Payload size must be less than or equal to 125");
|
||||
}
|
||||
this.sinkBuffer.writeByte(i | PeripheralType.SERVO);
|
||||
if (this.isClient) {
|
||||
this.sinkBuffer.writeByte(size | PeripheralType.SERVO);
|
||||
this.random.nextBytes(this.maskKey);
|
||||
this.sinkBuffer.write(this.maskKey);
|
||||
if (size > 0) {
|
||||
long size2 = this.sinkBuffer.size();
|
||||
this.sinkBuffer.write(byteString);
|
||||
this.sinkBuffer.readAndWriteUnsafe(this.maskCursor);
|
||||
this.maskCursor.seek(size2);
|
||||
WebSocketProtocol.toggleMask(this.maskCursor, this.maskKey);
|
||||
this.maskCursor.close();
|
||||
}
|
||||
} else {
|
||||
this.sinkBuffer.writeByte(size);
|
||||
this.sinkBuffer.write(byteString);
|
||||
}
|
||||
this.sink.flush();
|
||||
}
|
||||
|
||||
Sink newMessageSink(int i, long j) {
|
||||
if (this.activeWriter) {
|
||||
throw new IllegalStateException("Another message writer is active. Did you call close()?");
|
||||
}
|
||||
this.activeWriter = true;
|
||||
FrameSink frameSink = this.frameSink;
|
||||
frameSink.formatOpcode = i;
|
||||
frameSink.contentLength = j;
|
||||
frameSink.isFirstFrame = true;
|
||||
frameSink.closed = false;
|
||||
return frameSink;
|
||||
}
|
||||
|
||||
void writeClose(int i, ByteString byteString) throws IOException {
|
||||
ByteString byteString2 = ByteString.EMPTY;
|
||||
if (i != 0 || byteString != null) {
|
||||
if (i != 0) {
|
||||
WebSocketProtocol.validateCloseCode(i);
|
||||
}
|
||||
Buffer buffer = new Buffer();
|
||||
buffer.writeShort(i);
|
||||
if (byteString != null) {
|
||||
buffer.write(byteString);
|
||||
}
|
||||
byteString2 = buffer.readByteString();
|
||||
}
|
||||
try {
|
||||
writeControlFrame(8, byteString2);
|
||||
} finally {
|
||||
this.writerClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void writeMessageFrame(int i, long j, boolean z, boolean z2) throws IOException {
|
||||
if (this.writerClosed) {
|
||||
throw new IOException("closed");
|
||||
}
|
||||
if (!z) {
|
||||
i = 0;
|
||||
}
|
||||
if (z2) {
|
||||
i |= PeripheralType.SERVO;
|
||||
}
|
||||
this.sinkBuffer.writeByte(i);
|
||||
int i2 = this.isClient ? PeripheralType.SERVO : 0;
|
||||
if (j <= 125) {
|
||||
this.sinkBuffer.writeByte(((int) j) | i2);
|
||||
} else if (j <= 65535) {
|
||||
this.sinkBuffer.writeByte(i2 | 126);
|
||||
this.sinkBuffer.writeShort((int) j);
|
||||
} else {
|
||||
this.sinkBuffer.writeByte(i2 | 127);
|
||||
this.sinkBuffer.writeLong(j);
|
||||
}
|
||||
if (this.isClient) {
|
||||
this.random.nextBytes(this.maskKey);
|
||||
this.sinkBuffer.write(this.maskKey);
|
||||
if (j > 0) {
|
||||
long size = this.sinkBuffer.size();
|
||||
this.sinkBuffer.write(this.buffer, j);
|
||||
this.sinkBuffer.readAndWriteUnsafe(this.maskCursor);
|
||||
this.maskCursor.seek(size);
|
||||
WebSocketProtocol.toggleMask(this.maskCursor, this.maskKey);
|
||||
this.maskCursor.close();
|
||||
}
|
||||
} else {
|
||||
this.sinkBuffer.write(this.buffer, j);
|
||||
}
|
||||
this.sink.emit();
|
||||
}
|
||||
|
||||
void writePing(ByteString byteString) throws IOException {
|
||||
writeControlFrame(9, byteString);
|
||||
}
|
||||
|
||||
void writePong(ByteString byteString) throws IOException {
|
||||
writeControlFrame(10, byteString);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user