200 lines
7.3 KiB
Java
200 lines
7.3 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|