264 lines
9.7 KiB
Java
264 lines
9.7 KiB
Java
package io.grpc.okhttp;
|
|
|
|
import com.google.common.base.Preconditions;
|
|
import io.grpc.okhttp.internal.framed.FrameWriter;
|
|
import java.io.IOException;
|
|
import o.C15111ghZ;
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
/* loaded from: classes6.dex */
|
|
public class OutboundFlowController {
|
|
private final FrameWriter frameWriter;
|
|
private final OkHttpClientTransport transport;
|
|
private int initialWindowSize = 65535;
|
|
private final OutboundFlowState connectionState = new OutboundFlowState(this, 0, 65535);
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public OutboundFlowController(OkHttpClientTransport okHttpClientTransport, FrameWriter frameWriter) {
|
|
this.transport = (OkHttpClientTransport) Preconditions.checkNotNull(okHttpClientTransport, "transport");
|
|
this.frameWriter = (FrameWriter) Preconditions.checkNotNull(frameWriter, "frameWriter");
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public boolean initialOutboundWindowSize(int i) {
|
|
if (i < 0) {
|
|
throw new IllegalArgumentException("Invalid initial window size: ".concat(String.valueOf(i)));
|
|
}
|
|
int i2 = i - this.initialWindowSize;
|
|
this.initialWindowSize = i;
|
|
for (OkHttpClientStream okHttpClientStream : this.transport.getActiveStreams()) {
|
|
OutboundFlowState outboundFlowState = (OutboundFlowState) okHttpClientStream.getOutboundFlowState();
|
|
if (outboundFlowState == null) {
|
|
okHttpClientStream.setOutboundFlowState(new OutboundFlowState(this, okHttpClientStream, this.initialWindowSize));
|
|
} else {
|
|
outboundFlowState.incrementStreamWindow(i2);
|
|
}
|
|
}
|
|
return i2 > 0;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public int windowUpdate(OkHttpClientStream okHttpClientStream, int i) {
|
|
if (okHttpClientStream == null) {
|
|
int incrementStreamWindow = this.connectionState.incrementStreamWindow(i);
|
|
writeStreams();
|
|
return incrementStreamWindow;
|
|
}
|
|
OutboundFlowState state = state(okHttpClientStream);
|
|
int incrementStreamWindow2 = state.incrementStreamWindow(i);
|
|
WriteStatus writeStatus = new WriteStatus();
|
|
state.writeBytes(state.writableWindow(), writeStatus);
|
|
if (writeStatus.hasWritten()) {
|
|
flush();
|
|
}
|
|
return incrementStreamWindow2;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public void data(boolean z, int i, C15111ghZ c15111ghZ, boolean z2) {
|
|
Preconditions.checkNotNull(c15111ghZ, "source");
|
|
OkHttpClientStream stream = this.transport.getStream(i);
|
|
if (stream == null) {
|
|
return;
|
|
}
|
|
OutboundFlowState state = state(stream);
|
|
int writableWindow = state.writableWindow();
|
|
boolean hasPendingData = state.hasPendingData();
|
|
int i2 = (int) c15111ghZ.c;
|
|
if (!hasPendingData && writableWindow >= i2) {
|
|
state.write(c15111ghZ, i2, z);
|
|
} else {
|
|
if (!hasPendingData && writableWindow > 0) {
|
|
state.write(c15111ghZ, writableWindow, false);
|
|
}
|
|
state.enqueue(c15111ghZ, (int) c15111ghZ.c, z);
|
|
}
|
|
if (z2) {
|
|
flush();
|
|
}
|
|
}
|
|
|
|
void flush() {
|
|
try {
|
|
this.frameWriter.flush();
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private OutboundFlowState state(OkHttpClientStream okHttpClientStream) {
|
|
OutboundFlowState outboundFlowState = (OutboundFlowState) okHttpClientStream.getOutboundFlowState();
|
|
if (outboundFlowState != null) {
|
|
return outboundFlowState;
|
|
}
|
|
OutboundFlowState outboundFlowState2 = new OutboundFlowState(this, okHttpClientStream, this.initialWindowSize);
|
|
okHttpClientStream.setOutboundFlowState(outboundFlowState2);
|
|
return outboundFlowState2;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
public void writeStreams() {
|
|
int i;
|
|
OkHttpClientStream[] activeStreams = this.transport.getActiveStreams();
|
|
int window = this.connectionState.window();
|
|
int length = activeStreams.length;
|
|
while (true) {
|
|
i = 0;
|
|
if (length <= 0 || window <= 0) {
|
|
break;
|
|
}
|
|
int ceil = (int) Math.ceil(window / length);
|
|
for (int i2 = 0; i2 < length && window > 0; i2++) {
|
|
OkHttpClientStream okHttpClientStream = activeStreams[i2];
|
|
OutboundFlowState state = state(okHttpClientStream);
|
|
int min = Math.min(window, Math.min(state.unallocatedBytes(), ceil));
|
|
if (min > 0) {
|
|
state.allocateBytes(min);
|
|
window -= min;
|
|
}
|
|
if (state.unallocatedBytes() > 0) {
|
|
activeStreams[i] = okHttpClientStream;
|
|
i++;
|
|
}
|
|
}
|
|
length = i;
|
|
}
|
|
WriteStatus writeStatus = new WriteStatus();
|
|
OkHttpClientStream[] activeStreams2 = this.transport.getActiveStreams();
|
|
int length2 = activeStreams2.length;
|
|
while (i < length2) {
|
|
OutboundFlowState state2 = state(activeStreams2[i]);
|
|
state2.writeBytes(state2.allocatedBytes(), writeStatus);
|
|
state2.clearAllocatedBytes();
|
|
i++;
|
|
}
|
|
if (writeStatus.hasWritten()) {
|
|
flush();
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
/* loaded from: classes6.dex */
|
|
public static final class WriteStatus {
|
|
int numWrites;
|
|
|
|
private WriteStatus() {
|
|
}
|
|
|
|
final void incrementNumWrites() {
|
|
this.numWrites++;
|
|
}
|
|
|
|
final boolean hasWritten() {
|
|
return this.numWrites > 0;
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: package-private */
|
|
/* loaded from: classes6.dex */
|
|
public final class OutboundFlowState {
|
|
int allocatedBytes;
|
|
boolean pendingBufferHasEndOfStream;
|
|
final C15111ghZ pendingWriteBuffer;
|
|
OkHttpClientStream stream;
|
|
final int streamId;
|
|
final OutboundFlowController this$0;
|
|
int window;
|
|
|
|
OutboundFlowState(OutboundFlowController outboundFlowController, int i, int i2) {
|
|
this.this$0 = outboundFlowController;
|
|
this.pendingBufferHasEndOfStream = false;
|
|
this.streamId = i;
|
|
this.window = i2;
|
|
this.pendingWriteBuffer = new C15111ghZ();
|
|
}
|
|
|
|
OutboundFlowState(OutboundFlowController outboundFlowController, OkHttpClientStream okHttpClientStream, int i) {
|
|
this(outboundFlowController, okHttpClientStream.id(), i);
|
|
this.stream = okHttpClientStream;
|
|
}
|
|
|
|
final int unallocatedBytes() {
|
|
return streamableBytes() - this.allocatedBytes;
|
|
}
|
|
|
|
final int incrementStreamWindow(int i) {
|
|
if (i <= 0 || Integer.MAX_VALUE - i >= this.window) {
|
|
int i2 = this.window + i;
|
|
this.window = i2;
|
|
return i2;
|
|
}
|
|
StringBuilder sb = new StringBuilder("Window size overflow for stream: ");
|
|
sb.append(this.streamId);
|
|
throw new IllegalArgumentException(sb.toString());
|
|
}
|
|
|
|
final int writableWindow() {
|
|
return Math.min(this.window, this.this$0.connectionState.window());
|
|
}
|
|
|
|
final int writeBytes(int i, WriteStatus writeStatus) {
|
|
int min = Math.min(i, writableWindow());
|
|
int i2 = 0;
|
|
while (hasPendingData() && min > 0) {
|
|
if (min < this.pendingWriteBuffer.c) {
|
|
i2 += min;
|
|
write(this.pendingWriteBuffer, min, false);
|
|
} else {
|
|
i2 += (int) this.pendingWriteBuffer.c;
|
|
C15111ghZ c15111ghZ = this.pendingWriteBuffer;
|
|
write(c15111ghZ, (int) c15111ghZ.c, this.pendingBufferHasEndOfStream);
|
|
}
|
|
writeStatus.incrementNumWrites();
|
|
min = Math.min(i - i2, writableWindow());
|
|
}
|
|
return i2;
|
|
}
|
|
|
|
final void write(C15111ghZ c15111ghZ, int i, boolean z) {
|
|
do {
|
|
int min = Math.min(i, this.this$0.frameWriter.maxDataLength());
|
|
int i2 = -min;
|
|
this.this$0.connectionState.incrementStreamWindow(i2);
|
|
incrementStreamWindow(i2);
|
|
try {
|
|
this.this$0.frameWriter.data(c15111ghZ.c == ((long) min) && z, this.streamId, c15111ghZ, min);
|
|
this.stream.transportState().onSentBytes(min);
|
|
i -= min;
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
} while (i > 0);
|
|
}
|
|
|
|
final void enqueue(C15111ghZ c15111ghZ, int i, boolean z) {
|
|
this.pendingWriteBuffer.write(c15111ghZ, i);
|
|
this.pendingBufferHasEndOfStream |= z;
|
|
}
|
|
|
|
final boolean hasPendingData() {
|
|
return this.pendingWriteBuffer.c > 0;
|
|
}
|
|
|
|
final int streamableBytes() {
|
|
return Math.max(0, Math.min(this.window, (int) this.pendingWriteBuffer.c));
|
|
}
|
|
|
|
final int window() {
|
|
return this.window;
|
|
}
|
|
|
|
final void clearAllocatedBytes() {
|
|
this.allocatedBytes = 0;
|
|
}
|
|
|
|
final int allocatedBytes() {
|
|
return this.allocatedBytes;
|
|
}
|
|
|
|
final void allocateBytes(int i) {
|
|
this.allocatedBytes += i;
|
|
}
|
|
}
|
|
}
|