Initial commit

This commit is contained in:
2025-05-13 19:24:51 +02:00
commit a950f49678
10604 changed files with 932663 additions and 0 deletions

View 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;
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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);
}
}