package io.grpc.internal; import com.google.common.base.Preconditions; import com.google.common.io.ByteStreams; import io.grpc.Codec; import io.grpc.Compressor; import io.grpc.Drainable; import io.grpc.KnownLength; import io.grpc.Status; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /* loaded from: classes6.dex */ public class MessageFramer implements Framer { private static final byte COMPRESSED = 1; private static final int HEADER_LENGTH = 5; private static final int NO_MAX_OUTBOUND_MESSAGE_SIZE = -1; private static final byte UNCOMPRESSED = 0; private WritableBuffer buffer; private final WritableBufferAllocator bufferAllocator; private boolean closed; private long currentMessageWireSize; private int messagesBuffered; private final Sink sink; private final StatsTraceContext statsTraceCtx; private int maxOutboundMessageSize = -1; private Compressor compressor = Codec.Identity.NONE; private boolean messageCompression = true; private final OutputStreamAdapter outputStreamAdapter = new OutputStreamAdapter(); private final ByteBuffer headerScratch = ByteBuffer.allocate(5); private int currentMessageSeqNo = -1; /* loaded from: classes6.dex */ public interface Sink { void deliverFrame(WritableBuffer writableBuffer, boolean z, boolean z2, int i); } public MessageFramer(Sink sink, WritableBufferAllocator writableBufferAllocator, StatsTraceContext statsTraceContext) { this.sink = (Sink) Preconditions.checkNotNull(sink, "sink"); this.bufferAllocator = (WritableBufferAllocator) Preconditions.checkNotNull(writableBufferAllocator, "bufferAllocator"); this.statsTraceCtx = (StatsTraceContext) Preconditions.checkNotNull(statsTraceContext, "statsTraceCtx"); } @Override // io.grpc.internal.Framer public MessageFramer setCompressor(Compressor compressor) { this.compressor = (Compressor) Preconditions.checkNotNull(compressor, "Can't pass an empty compressor"); return this; } @Override // io.grpc.internal.Framer public void setMaxOutboundMessageSize(int i) { Preconditions.checkState(this.maxOutboundMessageSize == -1, "max size already set"); this.maxOutboundMessageSize = i; } @Override // io.grpc.internal.Framer public void writePayload(InputStream inputStream) { int writeUncompressed; verifyNotClosed(); this.messagesBuffered++; int i = this.currentMessageSeqNo + 1; this.currentMessageSeqNo = i; this.currentMessageWireSize = 0L; this.statsTraceCtx.outboundMessage(i); boolean z = this.messageCompression && this.compressor != Codec.Identity.NONE; try { int knownLength = getKnownLength(inputStream); if (knownLength != 0 && z) { writeUncompressed = writeCompressed(inputStream, knownLength); } else { writeUncompressed = writeUncompressed(inputStream, knownLength); } if (knownLength != -1 && writeUncompressed != knownLength) { throw Status.INTERNAL.withDescription(String.format("Message length inaccurate %s != %s", Integer.valueOf(writeUncompressed), Integer.valueOf(knownLength))).asRuntimeException(); } long j = writeUncompressed; this.statsTraceCtx.outboundUncompressedSize(j); this.statsTraceCtx.outboundWireSize(this.currentMessageWireSize); this.statsTraceCtx.outboundMessageSent(this.currentMessageSeqNo, this.currentMessageWireSize, j); } catch (IOException e) { throw Status.INTERNAL.withDescription("Failed to frame message").withCause(e).asRuntimeException(); } catch (RuntimeException e2) { throw Status.INTERNAL.withDescription("Failed to frame message").withCause(e2).asRuntimeException(); } } private int writeUncompressed(InputStream inputStream, int i) throws IOException { if (i != -1) { this.currentMessageWireSize = i; return writeKnownLengthUncompressed(inputStream, i); } BufferChainOutputStream bufferChainOutputStream = new BufferChainOutputStream(); int writeToOutputStream = writeToOutputStream(inputStream, bufferChainOutputStream); int i2 = this.maxOutboundMessageSize; if (i2 >= 0 && writeToOutputStream > i2) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format("message too large %d > %d", Integer.valueOf(writeToOutputStream), Integer.valueOf(this.maxOutboundMessageSize))).asRuntimeException(); } writeBufferChain(bufferChainOutputStream, false); return writeToOutputStream; } private int writeCompressed(InputStream inputStream, int i) throws IOException { BufferChainOutputStream bufferChainOutputStream = new BufferChainOutputStream(); OutputStream compress = this.compressor.compress(bufferChainOutputStream); try { int writeToOutputStream = writeToOutputStream(inputStream, compress); compress.close(); int i2 = this.maxOutboundMessageSize; if (i2 >= 0 && writeToOutputStream > i2) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format("message too large %d > %d", Integer.valueOf(writeToOutputStream), Integer.valueOf(this.maxOutboundMessageSize))).asRuntimeException(); } writeBufferChain(bufferChainOutputStream, true); return writeToOutputStream; } catch (Throwable th) { compress.close(); throw th; } } private int getKnownLength(InputStream inputStream) throws IOException { if ((inputStream instanceof KnownLength) || (inputStream instanceof ByteArrayInputStream)) { return inputStream.available(); } return -1; } private int writeKnownLengthUncompressed(InputStream inputStream, int i) throws IOException { int i2 = this.maxOutboundMessageSize; if (i2 >= 0 && i > i2) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format("message too large %d > %d", Integer.valueOf(i), Integer.valueOf(this.maxOutboundMessageSize))).asRuntimeException(); } this.headerScratch.clear(); this.headerScratch.put((byte) 0).putInt(i); if (this.buffer == null) { this.buffer = this.bufferAllocator.allocate(this.headerScratch.position() + i); } writeRaw(this.headerScratch.array(), 0, this.headerScratch.position()); return writeToOutputStream(inputStream, this.outputStreamAdapter); } private void writeBufferChain(BufferChainOutputStream bufferChainOutputStream, boolean z) { int readableBytes = bufferChainOutputStream.readableBytes(); this.headerScratch.clear(); this.headerScratch.put(z ? (byte) 1 : (byte) 0).putInt(readableBytes); WritableBuffer allocate = this.bufferAllocator.allocate(5); allocate.write(this.headerScratch.array(), 0, this.headerScratch.position()); if (readableBytes == 0) { this.buffer = allocate; return; } this.sink.deliverFrame(allocate, false, false, this.messagesBuffered - 1); this.messagesBuffered = 1; List list = bufferChainOutputStream.bufferList; for (int i = 0; i < list.size() - 1; i++) { this.sink.deliverFrame((WritableBuffer) list.get(i), false, false, 0); } this.buffer = (WritableBuffer) list.get(list.size() - 1); this.currentMessageWireSize = readableBytes; } /* JADX WARN: Multi-variable type inference failed */ private static int writeToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException { if (inputStream instanceof Drainable) { return ((Drainable) inputStream).drainTo(outputStream); } long copy = ByteStreams.copy(inputStream, outputStream); Preconditions.checkArgument(copy <= 2147483647L, "Message size overflow: %s", copy); return (int) copy; } /* JADX INFO: Access modifiers changed from: private */ public void writeRaw(byte[] bArr, int i, int i2) { while (i2 > 0) { WritableBuffer writableBuffer = this.buffer; if (writableBuffer != null && writableBuffer.writableBytes() == 0) { commitToSink(false, false); } if (this.buffer == null) { this.buffer = this.bufferAllocator.allocate(i2); } int min = Math.min(i2, this.buffer.writableBytes()); this.buffer.write(bArr, i, min); i += min; i2 -= min; } } @Override // io.grpc.internal.Framer public void flush() { WritableBuffer writableBuffer = this.buffer; if (writableBuffer == null || writableBuffer.readableBytes() <= 0) { return; } commitToSink(false, true); } @Override // io.grpc.internal.Framer public void close() { if (isClosed()) { return; } this.closed = true; WritableBuffer writableBuffer = this.buffer; if (writableBuffer != null && writableBuffer.readableBytes() == 0) { releaseBuffer(); } commitToSink(true, true); } @Override // io.grpc.internal.Framer public void dispose() { this.closed = true; releaseBuffer(); } private void releaseBuffer() { WritableBuffer writableBuffer = this.buffer; if (writableBuffer != null) { writableBuffer.release(); this.buffer = null; } } private void commitToSink(boolean z, boolean z2) { WritableBuffer writableBuffer = this.buffer; this.buffer = null; this.sink.deliverFrame(writableBuffer, z, z2, this.messagesBuffered); this.messagesBuffered = 0; } private void verifyNotClosed() { if (isClosed()) { throw new IllegalStateException("Framer already closed"); } } /* JADX INFO: Access modifiers changed from: package-private */ /* loaded from: classes6.dex */ public class OutputStreamAdapter extends OutputStream { final MessageFramer this$0; private OutputStreamAdapter(MessageFramer messageFramer) { this.this$0 = messageFramer; } @Override // java.io.OutputStream public void write(int i) { write(new byte[]{(byte) i}, 0, 1); } @Override // java.io.OutputStream public void write(byte[] bArr, int i, int i2) { this.this$0.writeRaw(bArr, i, i2); } } /* JADX INFO: Access modifiers changed from: package-private */ /* loaded from: classes6.dex */ public final class BufferChainOutputStream extends OutputStream { private final List bufferList; private WritableBuffer current; final MessageFramer this$0; private BufferChainOutputStream(MessageFramer messageFramer) { this.this$0 = messageFramer; this.bufferList = new ArrayList(); } @Override // java.io.OutputStream public final void write(int i) throws IOException { WritableBuffer writableBuffer = this.current; if (writableBuffer != null && writableBuffer.writableBytes() > 0) { this.current.write((byte) i); } else { write(new byte[]{(byte) i}, 0, 1); } } @Override // java.io.OutputStream public final void write(byte[] bArr, int i, int i2) { if (this.current == null) { WritableBuffer allocate = this.this$0.bufferAllocator.allocate(i2); this.current = allocate; this.bufferList.add(allocate); } while (i2 > 0) { int min = Math.min(i2, this.current.writableBytes()); if (min == 0) { WritableBuffer allocate2 = this.this$0.bufferAllocator.allocate(Math.max(i2, this.current.readableBytes() << 1)); this.current = allocate2; this.bufferList.add(allocate2); } else { this.current.write(bArr, i, min); i += min; i2 -= min; } } } /* JADX INFO: Access modifiers changed from: private */ public int readableBytes() { Iterator it = this.bufferList.iterator(); int i = 0; while (it.hasNext()) { i += it.next().readableBytes(); } return i; } } @Override // io.grpc.internal.Framer public MessageFramer setMessageCompression(boolean z) { this.messageCompression = z; return this; } @Override // io.grpc.internal.Framer public boolean isClosed() { return this.closed; } }