CarrotChat v2.8.80.240429版本的 MD5 值为:fdf98761f01e715a89df24b85b0d206e
以下内容为反编译后的 InBandBytestreamSession.java 源代码,内容仅作参考
package org.jivesoftware.smackx.bytestreams.ibb;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
import org.jivesoftware.smackx.bytestreams.ibb.packet.Close;
import org.jivesoftware.smackx.bytestreams.ibb.packet.Data;
import org.jivesoftware.smackx.bytestreams.ibb.packet.DataPacketExtension;
import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
import org.jxmpp.jid.Jid;
public class InBandBytestreamSession implements BytestreamSession {
private final Open byteStreamRequest;
private final XMPPConnection connection;
private IBBInputStream inputStream;
private IBBOutputStream outputStream;
private Jid remoteJID;
private boolean closeBothStreamsEnabled = false;
private boolean isClosed = false;
static class AnonymousClass1 {
static final int[] $SwitchMap$org$jivesoftware$smackx$bytestreams$ibb$InBandBytestreamManager$StanzaType;
static {
int[] iArr = new int[InBandBytestreamManager.StanzaType.values().length];
$SwitchMap$org$jivesoftware$smackx$bytestreams$ibb$InBandBytestreamManager$StanzaType = iArr;
try {
iArr[InBandBytestreamManager.StanzaType.IQ.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
$SwitchMap$org$jivesoftware$smackx$bytestreams$ibb$InBandBytestreamManager$StanzaType[InBandBytestreamManager.StanzaType.MESSAGE.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
}
}
private class IBBDataPacketFilter implements StanzaFilter {
private IBBDataPacketFilter() {
}
@Override
public boolean accept(Stanza stanza) {
DataPacketExtension dataPacketExtension;
if (!stanza.getFrom().equals((CharSequence) InBandBytestreamSession.this.remoteJID)) {
return false;
}
if (stanza instanceof Data) {
dataPacketExtension = ((Data) stanza).getDataPacketExtension();
} else {
dataPacketExtension = (DataPacketExtension) stanza.getExtension("data", "http://jabber.org/protocol/ibb");
if (dataPacketExtension == null) {
return false;
}
}
if (!dataPacketExtension.getSessionID().equals(InBandBytestreamSession.this.byteStreamRequest.getSessionID())) {
return false;
}
return true;
}
IBBDataPacketFilter(InBandBytestreamSession inBandBytestreamSession, AnonymousClass1 anonymousClass1) {
this();
}
}
private class IQIBBInputStream extends IBBInputStream {
private IQIBBInputStream() {
super();
}
@Override
protected StanzaFilter getDataPacketFilter() {
return new AndFilter(new StanzaTypeFilter(Data.class), new IBBDataPacketFilter(InBandBytestreamSession.this, null));
}
@Override
protected StanzaListener getDataPacketListener() {
return new StanzaListener() {
private long lastSequence = -1;
@Override
public void processStanza(Stanza stanza) throws SmackException.NotConnectedException, InterruptedException {
DataPacketExtension dataPacketExtension = ((Data) stanza).getDataPacketExtension();
if (dataPacketExtension.getSeq() <= this.lastSequence) {
InBandBytestreamSession.this.connection.sendStanza(IQ.createErrorResponse((IQ) stanza, XMPPError.Condition.unexpected_request));
return;
}
if (dataPacketExtension.getDecodedData() == null) {
InBandBytestreamSession.this.connection.sendStanza(IQ.createErrorResponse((IQ) stanza, XMPPError.Condition.bad_request));
return;
}
IQIBBInputStream.this.dataQueue.offer(dataPacketExtension);
InBandBytestreamSession.this.connection.sendStanza(IQ.createResultIQ((IQ) stanza));
long seq = dataPacketExtension.getSeq();
this.lastSequence = seq;
if (seq == 65535) {
this.lastSequence = -1L;
}
}
};
}
IQIBBInputStream(InBandBytestreamSession inBandBytestreamSession, AnonymousClass1 anonymousClass1) {
this();
}
}
private class IQIBBOutputStream extends IBBOutputStream {
private IQIBBOutputStream() {
super();
}
@Override
protected synchronized void writeToXML(DataPacketExtension dataPacketExtension) throws IOException {
Data data = new Data(dataPacketExtension);
data.setTo(InBandBytestreamSession.this.remoteJID);
try {
InBandBytestreamSession.this.connection.createStanzaCollectorAndSend(data).nextResultOrThrow();
} catch (Exception e10) {
if (!this.isClosed) {
InBandBytestreamSession.this.close();
IOException iOException = new IOException();
iOException.initCause(e10);
throw iOException;
}
}
}
IQIBBOutputStream(InBandBytestreamSession inBandBytestreamSession, AnonymousClass1 anonymousClass1) {
this();
}
}
private class MessageIBBInputStream extends IBBInputStream {
private MessageIBBInputStream() {
super();
}
@Override
protected StanzaFilter getDataPacketFilter() {
return new AndFilter(new StanzaTypeFilter(Message.class), new IBBDataPacketFilter(InBandBytestreamSession.this, null));
}
@Override
protected StanzaListener getDataPacketListener() {
return new StanzaListener() {
@Override
public void processStanza(Stanza stanza) {
DataPacketExtension dataPacketExtension = (DataPacketExtension) stanza.getExtension("data", "http://jabber.org/protocol/ibb");
if (dataPacketExtension.getDecodedData() == null) {
return;
}
MessageIBBInputStream.this.dataQueue.offer(dataPacketExtension);
}
};
}
MessageIBBInputStream(InBandBytestreamSession inBandBytestreamSession, AnonymousClass1 anonymousClass1) {
this();
}
}
private class MessageIBBOutputStream extends IBBOutputStream {
private MessageIBBOutputStream() {
super();
}
@Override
protected synchronized void writeToXML(DataPacketExtension dataPacketExtension) throws SmackException.NotConnectedException, InterruptedException {
Message message = new Message(InBandBytestreamSession.this.remoteJID);
message.addExtension(dataPacketExtension);
InBandBytestreamSession.this.connection.sendStanza(message);
}
MessageIBBOutputStream(InBandBytestreamSession inBandBytestreamSession, AnonymousClass1 anonymousClass1) {
this();
}
}
public InBandBytestreamSession(XMPPConnection xMPPConnection, Open open, Jid jid) {
this.connection = xMPPConnection;
this.byteStreamRequest = open;
this.remoteJID = jid;
int i10 = AnonymousClass1.$SwitchMap$org$jivesoftware$smackx$bytestreams$ibb$InBandBytestreamManager$StanzaType[open.getStanza().ordinal()];
AnonymousClass1 anonymousClass1 = null;
if (i10 != 1) {
if (i10 == 2) {
this.inputStream = new MessageIBBInputStream(this, anonymousClass1);
this.outputStream = new MessageIBBOutputStream(this, anonymousClass1);
return;
}
return;
}
this.inputStream = new IQIBBInputStream(this, anonymousClass1);
this.outputStream = new IQIBBOutputStream(this, anonymousClass1);
}
@Override
public void close() throws IOException {
closeByLocal(true);
closeByLocal(false);
}
protected synchronized void closeByLocal(boolean z10) throws IOException {
if (this.isClosed) {
return;
}
if (this.closeBothStreamsEnabled) {
this.inputStream.closeInternal();
this.outputStream.closeInternal(true);
} else if (z10) {
this.inputStream.closeInternal();
} else {
this.outputStream.closeInternal(true);
}
if (this.inputStream.isClosed && this.outputStream.isClosed) {
this.isClosed = true;
Close close = new Close(this.byteStreamRequest.getSessionID());
close.setTo(this.remoteJID);
try {
this.connection.createStanzaCollectorAndSend(close).nextResultOrThrow();
this.inputStream.cleanup();
InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(this.byteStreamRequest.getSessionID());
} catch (Exception e10) {
IOException iOException = new IOException();
iOException.initCause(e10);
throw iOException;
}
}
}
public void closeByPeer(Close close) throws SmackException.NotConnectedException, InterruptedException {
this.inputStream.closeInternal();
this.inputStream.cleanup();
this.outputStream.closeInternal(false);
this.connection.sendStanza(IQ.createResultIQ(close));
}
@Override
public InputStream getInputStream() {
return this.inputStream;
}
@Override
public OutputStream getOutputStream() {
return this.outputStream;
}
@Override
public int getReadTimeout() {
return this.inputStream.readTimeout;
}
public boolean isCloseBothStreamsEnabled() {
return this.closeBothStreamsEnabled;
}
public void processIQPacket(Data data) throws SmackException.NotConnectedException, InterruptedException, SmackException.NotLoggedInException {
this.inputStream.dataPacketListener.processStanza(data);
}
public void setCloseBothStreamsEnabled(boolean z10) {
this.closeBothStreamsEnabled = z10;
}
@Override
public void setReadTimeout(int i10) {
if (i10 >= 0) {
this.inputStream.readTimeout = i10;
return;
}
throw new IllegalArgumentException("Timeout must be >= 0");
}
public abstract class IBBInputStream extends InputStream {
private byte[] buffer;
private final StanzaListener dataPacketListener;
protected final BlockingQueue<DataPacketExtension> dataQueue = new LinkedBlockingQueue();
private int bufferPointer = -1;
private long seq = -1;
private boolean isClosed = false;
private boolean closeInvoked = false;
private int readTimeout = 0;
public IBBInputStream() {
StanzaListener dataPacketListener = getDataPacketListener();
this.dataPacketListener = dataPacketListener;
InBandBytestreamSession.this.connection.addSyncStanzaListener(dataPacketListener, getDataPacketFilter());
}
private void checkClosed() throws IOException {
if (!this.closeInvoked) {
return;
}
this.dataQueue.clear();
throw new IOException("Stream is closed");
}
public void cleanup() {
InBandBytestreamSession.this.connection.removeSyncStanzaListener(this.dataPacketListener);
}
public void closeInternal() {
if (this.isClosed) {
return;
}
this.isClosed = true;
}
private synchronized boolean loadBuffer() throws IOException {
DataPacketExtension poll;
try {
int i10 = this.readTimeout;
if (i10 == 0) {
poll = null;
while (poll == null) {
if (this.isClosed && this.dataQueue.isEmpty()) {
return false;
}
poll = this.dataQueue.poll(1000L, TimeUnit.MILLISECONDS);
}
} else {
poll = this.dataQueue.poll(i10, TimeUnit.MILLISECONDS);
if (poll == null) {
throw new SocketTimeoutException();
}
}
if (this.seq == 65535) {
this.seq = -1L;
}
long seq = poll.getSeq();
if (seq - 1 == this.seq) {
this.seq = seq;
this.buffer = poll.getDecodedData();
this.bufferPointer = 0;
return true;
}
InBandBytestreamSession.this.close();
throw new IOException("Packets out of sequence");
} catch (InterruptedException unused) {
Thread.currentThread().interrupt();
return false;
}
}
@Override
public void close() throws IOException {
if (this.closeInvoked) {
return;
}
this.closeInvoked = true;
InBandBytestreamSession.this.closeByLocal(true);
}
protected abstract StanzaFilter getDataPacketFilter();
protected abstract StanzaListener getDataPacketListener();
@Override
public boolean markSupported() {
return false;
}
@Override
public synchronized int read() throws IOException {
checkClosed();
int i10 = this.bufferPointer;
if ((i10 == -1 || i10 >= this.buffer.length) && !loadBuffer()) {
return -1;
}
byte[] bArr = this.buffer;
int i11 = this.bufferPointer;
this.bufferPointer = i11 + 1;
return bArr[i11] & 255;
}
@Override
public synchronized int read(byte[] bArr, int i10, int i11) throws IOException {
int i12;
if (bArr != null) {
if (i10 < 0 || i10 > bArr.length || i11 < 0 || (i12 = i10 + i11) > bArr.length || i12 < 0) {
throw new IndexOutOfBoundsException();
}
if (i11 == 0) {
return 0;
}
checkClosed();
int i13 = this.bufferPointer;
if ((i13 == -1 || i13 >= this.buffer.length) && !loadBuffer()) {
return -1;
}
byte[] bArr2 = this.buffer;
int length = bArr2.length;
int i14 = this.bufferPointer;
int i15 = length - i14;
if (i11 > i15) {
i11 = i15;
}
System.arraycopy(bArr2, i14, bArr, i10, i11);
this.bufferPointer += i11;
return i11;
}
throw new NullPointerException();
}
@Override
public synchronized int read(byte[] bArr) throws IOException {
return read(bArr, 0, bArr.length);
}
}
public abstract class IBBOutputStream extends OutputStream {
protected final byte[] buffer;
protected int bufferPointer = 0;
protected long seq = 0;
protected boolean isClosed = false;
public IBBOutputStream() {
this.buffer = new byte[InBandBytestreamSession.this.byteStreamRequest.getBlockSize()];
}
private synchronized void flushBuffer() throws IOException {
long j10;
int i10 = this.bufferPointer;
if (i10 == 0) {
return;
}
try {
writeToXML(new DataPacketExtension(InBandBytestreamSession.this.byteStreamRequest.getSessionID(), this.seq, Base64.encodeToString(this.buffer, 0, i10)));
this.bufferPointer = 0;
long j11 = this.seq;
if (j11 + 1 == 65535) {
j10 = 0;
} else {
j10 = j11 + 1;
}
this.seq = j10;
} catch (InterruptedException | SmackException.NotConnectedException e10) {
IOException iOException = new IOException();
iOException.initCause(e10);
throw iOException;
}
}
private synchronized void writeOut(byte[] bArr, int i10, int i11) throws IOException {
if (!this.isClosed) {
int i12 = 0;
byte[] bArr2 = this.buffer;
int length = bArr2.length;
int i13 = this.bufferPointer;
if (i11 > length - i13) {
i12 = bArr2.length - i13;
System.arraycopy(bArr, i10, bArr2, i13, i12);
this.bufferPointer += i12;
flushBuffer();
}
int i14 = i11 - i12;
System.arraycopy(bArr, i10 + i12, this.buffer, this.bufferPointer, i14);
this.bufferPointer += i14;
} else {
throw new IOException("Stream is closed");
}
}
@Override
public void close() throws IOException {
if (this.isClosed) {
return;
}
InBandBytestreamSession.this.closeByLocal(false);
}
protected void closeInternal(boolean z10) {
if (this.isClosed) {
return;
}
this.isClosed = true;
if (z10) {
try {
flushBuffer();
} catch (IOException unused) {
}
}
}
@Override
public synchronized void flush() throws IOException {
if (!this.isClosed) {
flushBuffer();
} else {
throw new IOException("Stream is closed");
}
}
@Override
public synchronized void write(int i10) throws IOException {
if (!this.isClosed) {
if (this.bufferPointer >= this.buffer.length) {
flushBuffer();
}
byte[] bArr = this.buffer;
int i11 = this.bufferPointer;
this.bufferPointer = i11 + 1;
bArr[i11] = (byte) i10;
} else {
throw new IOException("Stream is closed");
}
}
protected abstract void writeToXML(DataPacketExtension dataPacketExtension) throws IOException, SmackException.NotConnectedException, InterruptedException;
@Override
public synchronized void write(byte[] bArr, int i10, int i11) throws IOException {
int i12;
if (bArr != null) {
if (i10 < 0 || i10 > bArr.length || i11 < 0 || (i12 = i10 + i11) > bArr.length || i12 < 0) {
throw new IndexOutOfBoundsException();
}
if (i11 == 0) {
return;
}
if (!this.isClosed) {
byte[] bArr2 = this.buffer;
if (i11 >= bArr2.length) {
writeOut(bArr, i10, bArr2.length);
byte[] bArr3 = this.buffer;
write(bArr, i10 + bArr3.length, i11 - bArr3.length);
} else {
writeOut(bArr, i10, i11);
}
return;
}
throw new IOException("Stream is closed");
}
throw new NullPointerException();
}
@Override
public synchronized void write(byte[] bArr) throws IOException {
write(bArr, 0, bArr.length);
}
}
}