alexandroid/decompiled/jadx/sources/org/java_websocket/SSLSocketChannel2.java
KaKi87 a47fad5135 📦 Add decompiled Alexa 2.2.730155.0 (jadx, apktool, Hermes strings)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 00:04:16 +01:00

390 lines
14 KiB
Java

package org.java_websocket;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import okio.Buffer$$ExternalSyntheticBUOutline0;
import org.java_websocket.interfaces.ISSLChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Single$$ExternalSyntheticBUOutline0;
/* compiled from: r8-map-id-b9432e0f623b4a4bff4ba50a8a24c4aafad2c1e11092747b9fb5e6a22af5a940 */
/* loaded from: classes11.dex */
public class SSLSocketChannel2 implements ByteChannel, WrappedByteChannel, ISSLChannel {
static final /* synthetic */ boolean $assertionsDisabled = false;
protected static ByteBuffer emptybuffer = ByteBuffer.allocate(0);
protected ExecutorService exec;
protected ByteBuffer inCrypt;
protected ByteBuffer inData;
protected ByteBuffer outCrypt;
protected SSLEngineResult readEngineResult;
protected SelectionKey selectionKey;
protected SocketChannel socketChannel;
protected SSLEngine sslEngine;
protected List<Future<?>> tasks;
protected SSLEngineResult writeEngineResult;
private final Logger log = LoggerFactory.getLogger((Class<?>) SSLSocketChannel2.class);
protected int bufferallocations = 0;
private byte[] saveCryptData = null;
public SSLSocketChannel2(SocketChannel socketChannel, SSLEngine sSLEngine, ExecutorService executorService, SelectionKey selectionKey) throws IOException {
if (socketChannel == null || sSLEngine == null || executorService == null) {
Single$$ExternalSyntheticBUOutline0.m$3("parameter must not be null");
throw null;
}
this.socketChannel = socketChannel;
this.sslEngine = sSLEngine;
this.exec = executorService;
SSLEngineResult sSLEngineResult = new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, sSLEngine.getHandshakeStatus(), 0, 0);
this.writeEngineResult = sSLEngineResult;
this.readEngineResult = sSLEngineResult;
this.tasks = new ArrayList(3);
if (selectionKey != null) {
selectionKey.interestOps(selectionKey.interestOps() | 4);
this.selectionKey = selectionKey;
}
createBuffers(sSLEngine.getSession());
this.socketChannel.write(wrap(emptybuffer));
processHandshake();
}
private void consumeFutureUninterruptible(Future<?> future) {
while (true) {
try {
try {
future.get();
return;
} catch (InterruptedException unused) {
Thread.currentThread().interrupt();
}
} catch (ExecutionException e) {
Buffer$$ExternalSyntheticBUOutline0.m((Throwable) e);
return;
}
}
}
private boolean isHandShakeComplete() {
SSLEngineResult.HandshakeStatus handshakeStatus = this.sslEngine.getHandshakeStatus();
return handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED || handshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
private synchronized void processHandshake() throws IOException {
try {
if (this.sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
return;
}
if (!this.tasks.isEmpty()) {
Iterator<Future<?>> it2 = this.tasks.iterator();
while (it2.hasNext()) {
Future<?> next = it2.next();
if (!next.isDone()) {
if (isBlocking()) {
consumeFutureUninterruptible(next);
}
return;
}
it2.remove();
}
}
if (this.sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
if (!isBlocking() || this.readEngineResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
this.inCrypt.compact();
if (this.socketChannel.read(this.inCrypt) == -1) {
throw new IOException("connection closed unexpectedly by peer");
}
this.inCrypt.flip();
}
this.inData.compact();
unwrap();
if (this.readEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {
createBuffers(this.sslEngine.getSession());
return;
}
}
consumeDelegatedTasks();
if (this.tasks.isEmpty() || this.sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
this.socketChannel.write(wrap(emptybuffer));
if (this.writeEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {
createBuffers(this.sslEngine.getSession());
return;
}
}
this.bufferallocations = 1;
} catch (Throwable th) {
throw th;
}
}
private int readRemaining(ByteBuffer byteBuffer) throws SSLException {
boolean hasRemaining = this.inData.hasRemaining();
ByteBuffer byteBuffer2 = this.inData;
if (hasRemaining) {
return transfereTo(byteBuffer2, byteBuffer);
}
if (!byteBuffer2.hasRemaining()) {
this.inData.clear();
}
tryRestoreCryptedData();
if (!this.inCrypt.hasRemaining()) {
return 0;
}
unwrap();
int transfereTo = transfereTo(this.inData, byteBuffer);
if (this.readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) {
return -1;
}
if (transfereTo > 0) {
return transfereTo;
}
return 0;
}
private void saveCryptedData() {
ByteBuffer byteBuffer = this.inCrypt;
if (byteBuffer == null || byteBuffer.remaining() <= 0) {
return;
}
byte[] bArr = new byte[this.inCrypt.remaining()];
this.saveCryptData = bArr;
this.inCrypt.get(bArr);
}
private int transfereTo(ByteBuffer byteBuffer, ByteBuffer byteBuffer2) {
int remaining = byteBuffer.remaining();
int remaining2 = byteBuffer2.remaining();
if (remaining <= remaining2) {
byteBuffer2.put(byteBuffer);
return remaining;
}
int min = Math.min(remaining, remaining2);
for (int i = 0; i < min; i++) {
byteBuffer2.put(byteBuffer.get());
}
return min;
}
private void tryRestoreCryptedData() {
if (this.saveCryptData != null) {
this.inCrypt.clear();
this.inCrypt.put(this.saveCryptData);
this.inCrypt.flip();
this.saveCryptData = null;
}
}
private synchronized ByteBuffer unwrap() throws SSLException {
if (this.readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED && this.sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
try {
close();
} catch (IOException unused) {
}
}
while (true) {
int remaining = this.inData.remaining();
SSLEngineResult unwrap = this.sslEngine.unwrap(this.inCrypt, this.inData);
this.readEngineResult = unwrap;
if (unwrap.getStatus() != SSLEngineResult.Status.OK || (remaining == this.inData.remaining() && this.sslEngine.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP)) {
break;
}
}
this.inData.flip();
return this.inData;
}
private synchronized ByteBuffer wrap(ByteBuffer byteBuffer) throws SSLException {
this.outCrypt.compact();
this.writeEngineResult = this.sslEngine.wrap(byteBuffer, this.outCrypt);
this.outCrypt.flip();
return this.outCrypt;
}
@Override // java.nio.channels.Channel, java.io.Closeable, java.lang.AutoCloseable
public void close() throws IOException {
this.sslEngine.closeOutbound();
this.sslEngine.getSession().invalidate();
if (this.socketChannel.isOpen()) {
this.socketChannel.write(wrap(emptybuffer));
}
this.socketChannel.close();
}
public SelectableChannel configureBlocking(boolean z) throws IOException {
return this.socketChannel.configureBlocking(z);
}
public boolean connect(SocketAddress socketAddress) throws IOException {
return this.socketChannel.connect(socketAddress);
}
public void consumeDelegatedTasks() {
while (true) {
Runnable delegatedTask = this.sslEngine.getDelegatedTask();
if (delegatedTask == null) {
return;
} else {
this.tasks.add(this.exec.submit(delegatedTask));
}
}
}
public void createBuffers(SSLSession sSLSession) {
saveCryptedData();
int packetBufferSize = sSLSession.getPacketBufferSize();
int max = Math.max(sSLSession.getApplicationBufferSize(), packetBufferSize);
ByteBuffer byteBuffer = this.inData;
if (byteBuffer == null) {
this.inData = ByteBuffer.allocate(max);
this.outCrypt = ByteBuffer.allocate(packetBufferSize);
this.inCrypt = ByteBuffer.allocate(packetBufferSize);
} else {
if (byteBuffer.capacity() != max) {
this.inData = ByteBuffer.allocate(max);
}
if (this.outCrypt.capacity() != packetBufferSize) {
this.outCrypt = ByteBuffer.allocate(packetBufferSize);
}
if (this.inCrypt.capacity() != packetBufferSize) {
this.inCrypt = ByteBuffer.allocate(packetBufferSize);
}
}
if (this.inData.remaining() != 0 && this.log.isTraceEnabled()) {
this.log.trace(new String(this.inData.array(), this.inData.position(), this.inData.remaining()));
}
this.inData.rewind();
this.inData.flip();
if (this.inCrypt.remaining() != 0 && this.log.isTraceEnabled()) {
this.log.trace(new String(this.inCrypt.array(), this.inCrypt.position(), this.inCrypt.remaining()));
}
this.inCrypt.rewind();
this.inCrypt.flip();
this.outCrypt.rewind();
this.outCrypt.flip();
this.bufferallocations++;
}
public boolean finishConnect() throws IOException {
return this.socketChannel.finishConnect();
}
@Override // org.java_websocket.interfaces.ISSLChannel
public SSLEngine getSSLEngine() {
return this.sslEngine;
}
@Override // org.java_websocket.WrappedByteChannel
public boolean isBlocking() {
return this.socketChannel.isBlocking();
}
public boolean isConnected() {
return this.socketChannel.isConnected();
}
public boolean isInboundDone() {
return this.sslEngine.isInboundDone();
}
@Override // org.java_websocket.WrappedByteChannel
public boolean isNeedRead() {
if (this.saveCryptData != null || this.inData.hasRemaining()) {
return true;
}
return (!this.inCrypt.hasRemaining() || this.readEngineResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW || this.readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) ? false : true;
}
@Override // org.java_websocket.WrappedByteChannel
public boolean isNeedWrite() {
return this.outCrypt.hasRemaining() || !isHandShakeComplete();
}
@Override // java.nio.channels.Channel
public boolean isOpen() {
return this.socketChannel.isOpen();
}
@Override // java.nio.channels.ReadableByteChannel
public int read(ByteBuffer byteBuffer) throws IOException {
tryRestoreCryptedData();
while (byteBuffer.hasRemaining()) {
if (!isHandShakeComplete()) {
if (isBlocking()) {
while (!isHandShakeComplete()) {
processHandshake();
}
} else {
processHandshake();
if (!isHandShakeComplete()) {
return 0;
}
}
}
int readRemaining = readRemaining(byteBuffer);
if (readRemaining != 0) {
return readRemaining;
}
this.inData.clear();
boolean hasRemaining = this.inCrypt.hasRemaining();
ByteBuffer byteBuffer2 = this.inCrypt;
if (hasRemaining) {
byteBuffer2.compact();
} else {
byteBuffer2.clear();
}
if ((isBlocking() || this.readEngineResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) && this.socketChannel.read(this.inCrypt) == -1) {
return -1;
}
this.inCrypt.flip();
unwrap();
int transfereTo = transfereTo(this.inData, byteBuffer);
if (transfereTo != 0 || !isBlocking()) {
return transfereTo;
}
}
return 0;
}
@Override // org.java_websocket.WrappedByteChannel
public int readMore(ByteBuffer byteBuffer) throws SSLException {
return readRemaining(byteBuffer);
}
public Socket socket() {
return this.socketChannel.socket();
}
@Override // java.nio.channels.WritableByteChannel
public int write(ByteBuffer byteBuffer) throws IOException {
if (!isHandShakeComplete()) {
processHandshake();
return 0;
}
int write = this.socketChannel.write(wrap(byteBuffer));
if (this.writeEngineResult.getStatus() != SSLEngineResult.Status.CLOSED) {
return write;
}
Buffer$$ExternalSyntheticBUOutline0.m$3("Connection is closed");
return 0;
}
@Override // org.java_websocket.WrappedByteChannel
public void writeMore() throws IOException {
write(this.outCrypt);
}
}