package io.grpc.internal; import com.google.common.base.Preconditions; import io.grpc.Codec; import io.grpc.Decompressor; import io.grpc.Status; import io.grpc.internal.StreamListener; import java.io.Closeable; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.DataFormatException; /* loaded from: classes6.dex */ public class MessageDeframer implements Closeable, Deframer { private static final int COMPRESSED_FLAG_MASK = 1; private static final int HEADER_LENGTH = 5; private static final int MAX_BUFFER_SIZE = 2097152; private static final int RESERVED_MASK = 254; private boolean compressedFlag; private Decompressor decompressor; private GzipInflatingBuffer fullStreamDecompressor; private int inboundBodyWireSize; private byte[] inflatedBuffer; private int inflatedIndex; private Listener listener; private int maxInboundMessageSize; private CompositeReadableBuffer nextFrame; private long pendingDeliveries; private final StatsTraceContext statsTraceCtx; private final TransportTracer transportTracer; private State state = State.HEADER; private int requiredLength = 5; private CompositeReadableBuffer unprocessed = new CompositeReadableBuffer(); private boolean inDelivery = false; private int currentMessageSeqNo = -1; private boolean closeWhenComplete = false; private volatile boolean stopDelivery = false; /* loaded from: classes6.dex */ public interface Listener { void bytesRead(int i); void deframeFailed(Throwable th); void deframerClosed(boolean z); void messagesAvailable(StreamListener.MessageProducer messageProducer); } /* JADX INFO: Access modifiers changed from: package-private */ /* loaded from: classes6.dex */ public enum State { HEADER, BODY } public MessageDeframer(Listener listener, Decompressor decompressor, int i, StatsTraceContext statsTraceContext, TransportTracer transportTracer) { this.listener = (Listener) Preconditions.checkNotNull(listener, "sink"); this.decompressor = (Decompressor) Preconditions.checkNotNull(decompressor, "decompressor"); this.maxInboundMessageSize = i; this.statsTraceCtx = (StatsTraceContext) Preconditions.checkNotNull(statsTraceContext, "statsTraceCtx"); this.transportTracer = (TransportTracer) Preconditions.checkNotNull(transportTracer, "transportTracer"); } @Override // io.grpc.internal.Deframer public void setDecompressor(Decompressor decompressor) { Preconditions.checkState(this.fullStreamDecompressor == null, "Already set full stream decompressor"); this.decompressor = (Decompressor) Preconditions.checkNotNull(decompressor, "Can't pass an empty decompressor"); } @Override // io.grpc.internal.Deframer public void setFullStreamDecompressor(GzipInflatingBuffer gzipInflatingBuffer) { Preconditions.checkState(this.decompressor == Codec.Identity.NONE, "per-message decompressor already set"); Preconditions.checkState(this.fullStreamDecompressor == null, "full stream decompressor already set"); this.fullStreamDecompressor = (GzipInflatingBuffer) Preconditions.checkNotNull(gzipInflatingBuffer, "Can't pass a null full stream decompressor"); this.unprocessed = null; } @Override // io.grpc.internal.Deframer public void request(int i) { Preconditions.checkArgument(i > 0, "numMessages must be > 0"); if (isClosed()) { return; } this.pendingDeliveries += i; deliver(); } @Override // io.grpc.internal.Deframer public void deframe(ReadableBuffer readableBuffer) { boolean z; Preconditions.checkNotNull(readableBuffer, "data"); try { if (!isClosedOrScheduledToClose()) { GzipInflatingBuffer gzipInflatingBuffer = this.fullStreamDecompressor; if (gzipInflatingBuffer != null) { gzipInflatingBuffer.addGzippedBytes(readableBuffer); } else { this.unprocessed.addBuffer(readableBuffer); } try { deliver(); return; } catch (Throwable th) { th = th; z = false; if (z) { readableBuffer.close(); } throw th; } } readableBuffer.close(); } catch (Throwable th2) { th = th2; z = true; } } @Override // io.grpc.internal.Deframer public void closeWhenComplete() { if (isClosed()) { return; } if (isStalled()) { close(); } else { this.closeWhenComplete = true; } } @Override // java.io.Closeable, java.lang.AutoCloseable, io.grpc.internal.Deframer public void close() { if (isClosed()) { return; } CompositeReadableBuffer compositeReadableBuffer = this.nextFrame; boolean z = compositeReadableBuffer != null && compositeReadableBuffer.readableBytes() > 0; try { GzipInflatingBuffer gzipInflatingBuffer = this.fullStreamDecompressor; if (gzipInflatingBuffer != null) { boolean z2 = z || gzipInflatingBuffer.hasPartialData(); this.fullStreamDecompressor.close(); z = z2; } CompositeReadableBuffer compositeReadableBuffer2 = this.unprocessed; if (compositeReadableBuffer2 != null) { compositeReadableBuffer2.close(); } CompositeReadableBuffer compositeReadableBuffer3 = this.nextFrame; if (compositeReadableBuffer3 != null) { compositeReadableBuffer3.close(); } this.fullStreamDecompressor = null; this.unprocessed = null; this.nextFrame = null; this.listener.deframerClosed(z); } catch (Throwable th) { this.fullStreamDecompressor = null; this.unprocessed = null; this.nextFrame = null; throw th; } } private boolean isClosedOrScheduledToClose() { return isClosed() || this.closeWhenComplete; } private boolean isStalled() { GzipInflatingBuffer gzipInflatingBuffer = this.fullStreamDecompressor; if (gzipInflatingBuffer != null) { return gzipInflatingBuffer.isStalled(); } return this.unprocessed.readableBytes() == 0; } /* JADX INFO: Access modifiers changed from: package-private */ /* renamed from: io.grpc.internal.MessageDeframer$1, reason: invalid class name */ /* loaded from: classes6.dex */ public static /* synthetic */ class AnonymousClass1 { static final int[] $SwitchMap$io$grpc$internal$MessageDeframer$State; static { int[] iArr = new int[State.values().length]; $SwitchMap$io$grpc$internal$MessageDeframer$State = iArr; try { iArr[State.HEADER.ordinal()] = 1; } catch (NoSuchFieldError unused) { } try { $SwitchMap$io$grpc$internal$MessageDeframer$State[State.BODY.ordinal()] = 2; } catch (NoSuchFieldError unused2) { } } } private void deliver() { if (this.inDelivery) { return; } this.inDelivery = true; while (true) { try { if (this.stopDelivery || this.pendingDeliveries <= 0 || !readRequiredBytes()) { break; } int i = AnonymousClass1.$SwitchMap$io$grpc$internal$MessageDeframer$State[this.state.ordinal()]; if (i == 1) { processHeader(); } else if (i == 2) { processBody(); this.pendingDeliveries--; } else { StringBuilder sb = new StringBuilder(); sb.append("Invalid state: "); sb.append(this.state); throw new AssertionError(sb.toString()); } } finally { this.inDelivery = false; } } if (this.stopDelivery) { close(); return; } if (this.closeWhenComplete && isStalled()) { close(); } } private boolean readRequiredBytes() { int i; int i2 = 0; try { if (this.nextFrame == null) { this.nextFrame = new CompositeReadableBuffer(); } int i3 = 0; i = 0; while (true) { try { int readableBytes = this.requiredLength - this.nextFrame.readableBytes(); if (readableBytes <= 0) { if (i3 <= 0) { return true; } this.listener.bytesRead(i3); if (this.state != State.BODY) { return true; } if (this.fullStreamDecompressor != null) { this.statsTraceCtx.inboundWireSize(i); this.inboundBodyWireSize += i; return true; } this.statsTraceCtx.inboundWireSize(i3); this.inboundBodyWireSize += i3; return true; } if (this.fullStreamDecompressor != null) { try { byte[] bArr = this.inflatedBuffer; if (bArr == null || this.inflatedIndex == bArr.length) { this.inflatedBuffer = new byte[Math.min(readableBytes, 2097152)]; this.inflatedIndex = 0; } int inflateBytes = this.fullStreamDecompressor.inflateBytes(this.inflatedBuffer, this.inflatedIndex, Math.min(readableBytes, this.inflatedBuffer.length - this.inflatedIndex)); i3 += this.fullStreamDecompressor.getAndResetBytesConsumed(); i += this.fullStreamDecompressor.getAndResetDeflatedBytesConsumed(); if (inflateBytes == 0) { if (i3 > 0) { this.listener.bytesRead(i3); if (this.state == State.BODY) { if (this.fullStreamDecompressor != null) { this.statsTraceCtx.inboundWireSize(i); this.inboundBodyWireSize += i; } else { this.statsTraceCtx.inboundWireSize(i3); this.inboundBodyWireSize += i3; } } } return false; } this.nextFrame.addBuffer(ReadableBuffers.wrap(this.inflatedBuffer, this.inflatedIndex, inflateBytes)); this.inflatedIndex += inflateBytes; } catch (IOException e) { throw new RuntimeException(e); } catch (DataFormatException e2) { throw new RuntimeException(e2); } } else { if (this.unprocessed.readableBytes() == 0) { if (i3 > 0) { this.listener.bytesRead(i3); if (this.state == State.BODY) { if (this.fullStreamDecompressor != null) { this.statsTraceCtx.inboundWireSize(i); this.inboundBodyWireSize += i; } else { this.statsTraceCtx.inboundWireSize(i3); this.inboundBodyWireSize += i3; } } } return false; } int min = Math.min(readableBytes, this.unprocessed.readableBytes()); i3 += min; this.nextFrame.addBuffer(this.unprocessed.readBytes(min)); } } catch (Throwable th) { int i4 = i3; th = th; i2 = i4; if (i2 > 0) { this.listener.bytesRead(i2); if (this.state == State.BODY) { if (this.fullStreamDecompressor != null) { this.statsTraceCtx.inboundWireSize(i); this.inboundBodyWireSize += i; } else { this.statsTraceCtx.inboundWireSize(i2); this.inboundBodyWireSize += i2; } } } throw th; } } } catch (Throwable th2) { th = th2; i = 0; } } private void processHeader() { int readUnsignedByte = this.nextFrame.readUnsignedByte(); if ((readUnsignedByte & RESERVED_MASK) != 0) { throw Status.INTERNAL.withDescription("gRPC frame header malformed: reserved bits not zero").asRuntimeException(); } this.compressedFlag = (readUnsignedByte & 1) != 0; int readInt = this.nextFrame.readInt(); this.requiredLength = readInt; if (readInt < 0 || readInt > this.maxInboundMessageSize) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format("gRPC message exceeds maximum size %d: %d", Integer.valueOf(this.maxInboundMessageSize), Integer.valueOf(this.requiredLength))).asRuntimeException(); } int i = this.currentMessageSeqNo + 1; this.currentMessageSeqNo = i; this.statsTraceCtx.inboundMessage(i); this.transportTracer.reportMessageReceived(); this.state = State.BODY; } private void processBody() { this.statsTraceCtx.inboundMessageRead(this.currentMessageSeqNo, this.inboundBodyWireSize, -1L); this.inboundBodyWireSize = 0; InputStream compressedBody = this.compressedFlag ? getCompressedBody() : getUncompressedBody(); this.nextFrame = null; this.listener.messagesAvailable(new SingleMessageProducer(compressedBody, null)); this.state = State.HEADER; this.requiredLength = 5; } private InputStream getUncompressedBody() { this.statsTraceCtx.inboundUncompressedSize(this.nextFrame.readableBytes()); return ReadableBuffers.openStream(this.nextFrame, true); } private InputStream getCompressedBody() { if (this.decompressor == Codec.Identity.NONE) { throw Status.INTERNAL.withDescription("Can't decode compressed gRPC message as compression not configured").asRuntimeException(); } try { return new SizeEnforcingInputStream(this.decompressor.decompress(ReadableBuffers.openStream(this.nextFrame, true)), this.maxInboundMessageSize, this.statsTraceCtx); } catch (IOException e) { throw new RuntimeException(e); } } /* JADX INFO: Access modifiers changed from: package-private */ /* loaded from: classes6.dex */ public static final class SizeEnforcingInputStream extends FilterInputStream { private long count; private long mark; private long maxCount; private final int maxMessageSize; private final StatsTraceContext statsTraceCtx; SizeEnforcingInputStream(InputStream inputStream, int i, StatsTraceContext statsTraceContext) { super(inputStream); this.mark = -1L; this.maxMessageSize = i; this.statsTraceCtx = statsTraceContext; } @Override // java.io.FilterInputStream, java.io.InputStream public final int read() throws IOException { int read = ((FilterInputStream) this).in.read(); if (read != -1) { this.count++; } verifySize(); reportCount(); return read; } @Override // java.io.FilterInputStream, java.io.InputStream public final int read(byte[] bArr, int i, int i2) throws IOException { int read = ((FilterInputStream) this).in.read(bArr, i, i2); if (read != -1) { this.count += read; } verifySize(); reportCount(); return read; } @Override // java.io.FilterInputStream, java.io.InputStream public final long skip(long j) throws IOException { long skip = ((FilterInputStream) this).in.skip(j); this.count += skip; verifySize(); reportCount(); return skip; } @Override // java.io.FilterInputStream, java.io.InputStream public final void mark(int i) { synchronized (this) { ((FilterInputStream) this).in.mark(i); this.mark = this.count; } } @Override // java.io.FilterInputStream, java.io.InputStream public final void reset() throws IOException { synchronized (this) { if (!((FilterInputStream) this).in.markSupported()) { throw new IOException("Mark not supported"); } if (this.mark == -1) { throw new IOException("Mark not set"); } ((FilterInputStream) this).in.reset(); this.count = this.mark; } } private void reportCount() { long j = this.count; long j2 = this.maxCount; if (j > j2) { this.statsTraceCtx.inboundUncompressedSize(j - j2); this.maxCount = this.count; } } private void verifySize() { if (this.count > this.maxMessageSize) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format("Decompressed gRPC message exceeds maximum size %d", Integer.valueOf(this.maxMessageSize))).asRuntimeException(); } } } /* JADX INFO: Access modifiers changed from: package-private */ /* loaded from: classes6.dex */ public static class SingleMessageProducer implements StreamListener.MessageProducer { private InputStream message; /* synthetic */ SingleMessageProducer(InputStream inputStream, AnonymousClass1 anonymousClass1) { this(inputStream); } private SingleMessageProducer(InputStream inputStream) { this.message = inputStream; } @Override // io.grpc.internal.StreamListener.MessageProducer public InputStream next() { InputStream inputStream = this.message; this.message = null; return inputStream; } } /* JADX INFO: Access modifiers changed from: package-private */ public void stopDelivery() { this.stopDelivery = true; } @Override // io.grpc.internal.Deframer public void setMaxInboundMessageSize(int i) { this.maxInboundMessageSize = i; } /* JADX INFO: Access modifiers changed from: package-private */ public void setListener(Listener listener) { this.listener = listener; } public boolean isClosed() { return this.unprocessed == null && this.fullStreamDecompressor == null; } /* JADX INFO: Access modifiers changed from: package-private */ public boolean hasPendingDeliveries() { return this.pendingDeliveries != 0; } }