diff --git a/README.md b/README.md index 791dee6e908..fd2e6a06c12 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ For a guided tour, take a look at the [quick start guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC basics](https://grpc.io/docs/languages/java/basics). -The [examples](https://github.com/grpc/grpc-java/tree/v1.33.0/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.33.0/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.33.1/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.33.1/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -42,17 +42,17 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.33.0 + 1.33.1 io.grpc grpc-protobuf - 1.33.0 + 1.33.1 io.grpc grpc-stub - 1.33.0 + 1.33.1 org.apache.tomcat @@ -64,23 +64,23 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: Or for Gradle with non-Android, add to your dependencies: ```gradle -implementation 'io.grpc:grpc-netty-shaded:1.33.0' -implementation 'io.grpc:grpc-protobuf:1.33.0' -implementation 'io.grpc:grpc-stub:1.33.0' +implementation 'io.grpc:grpc-netty-shaded:1.33.1' +implementation 'io.grpc:grpc-protobuf:1.33.1' +implementation 'io.grpc:grpc-stub:1.33.1' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and `grpc-protobuf-lite` instead of `grpc-protobuf`: ```gradle -implementation 'io.grpc:grpc-okhttp:1.33.0' -implementation 'io.grpc:grpc-protobuf-lite:1.33.0' -implementation 'io.grpc:grpc-stub:1.33.0' +implementation 'io.grpc:grpc-okhttp:1.33.1' +implementation 'io.grpc:grpc-protobuf-lite:1.33.1' +implementation 'io.grpc:grpc-stub:1.33.1' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.33.0 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.33.1 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -112,7 +112,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.33.0:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.33.1:exe:${os.detected.classifier} @@ -142,7 +142,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.33.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' } } generateProtoTasks { diff --git a/api/src/main/java/io/grpc/ForwardingServerBuilder.java b/api/src/main/java/io/grpc/ForwardingServerBuilder.java index 4e1d5a1baf5..2a7bc0b164f 100644 --- a/api/src/main/java/io/grpc/ForwardingServerBuilder.java +++ b/api/src/main/java/io/grpc/ForwardingServerBuilder.java @@ -30,8 +30,7 @@ * @since 1.33.0 */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/7393") -public abstract class ForwardingServerBuilder> - extends ServerBuilder { +abstract class ForwardingServerBuilder> extends ServerBuilder { /** The default constructor. */ protected ForwardingServerBuilder() {} diff --git a/build.gradle b/build.gradle index dff0b7f479a..81747685a78 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.33.0" // CURRENT_GRPC_VERSION + version = "1.33.1" // CURRENT_GRPC_VERSION repositories { maven { // The google mirror is less flaky than mavenCentral() diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt index 1753171fb59..60d412f0c32 100644 --- a/compiler/src/test/golden/TestDeprecatedService.java.txt +++ b/compiler/src/test/golden/TestDeprecatedService.java.txt @@ -21,7 +21,7 @@ import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.33.0)", + value = "by gRPC proto compiler (version 1.33.1)", comments = "Source: grpc/testing/compiler/test.proto") @java.lang.Deprecated public final class TestDeprecatedServiceGrpc { diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index f6f7bf34571..d81ca257006 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -21,7 +21,7 @@ import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.33.0)", + value = "by gRPC proto compiler (version 1.33.1)", comments = "Source: grpc/testing/compiler/test.proto") public final class TestServiceGrpc { diff --git a/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt index 15804335d67..4ad81e1467f 100644 --- a/compiler/src/testLite/golden/TestDeprecatedService.java.txt +++ b/compiler/src/testLite/golden/TestDeprecatedService.java.txt @@ -21,7 +21,7 @@ import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.33.0)", + value = "by gRPC proto compiler (version 1.33.1)", comments = "Source: grpc/testing/compiler/test.proto") @java.lang.Deprecated public final class TestDeprecatedServiceGrpc { diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt index fb24ab020a2..13e61e5f838 100644 --- a/compiler/src/testLite/golden/TestService.java.txt +++ b/compiler/src/testLite/golden/TestService.java.txt @@ -21,7 +21,7 @@ import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.33.0)", + value = "by gRPC proto compiler (version 1.33.1)", comments = "Source: grpc/testing/compiler/test.proto") public final class TestServiceGrpc { diff --git a/context/src/main/java/io/grpc/Deadline.java b/context/src/main/java/io/grpc/Deadline.java index c7b50e0929a..73c87605953 100644 --- a/context/src/main/java/io/grpc/Deadline.java +++ b/context/src/main/java/io/grpc/Deadline.java @@ -17,6 +17,7 @@ package io.grpc; import java.util.Arrays; +import java.util.Locale; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -206,7 +207,7 @@ public String toString() { } buf.append(seconds); if (nanos > 0) { - buf.append(String.format(".%09d", nanos)); + buf.append(String.format(Locale.US, ".%09d", nanos)); } buf.append("s from now"); if (ticker != SYSTEM_TICKER) { diff --git a/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java b/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java index 926c7835729..63069f2ea71 100644 --- a/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java +++ b/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java @@ -21,9 +21,9 @@ import io.grpc.ChannelLogger; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingChannelBuilder; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.internal.AbstractManagedChannelImplBuilder; import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ConnectionClientTransport; import io.grpc.internal.GrpcUtil; @@ -45,7 +45,7 @@ */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1783") public final class InProcessChannelBuilder extends - ForwardingChannelBuilder { + AbstractManagedChannelImplBuilder { /** * Create a channel builder that will connect to the server with the given name. * diff --git a/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java b/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java index 37e6dcaede5..f768c608b16 100644 --- a/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java +++ b/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java @@ -21,10 +21,10 @@ import com.google.common.base.Preconditions; import io.grpc.Deadline; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingServerBuilder; import io.grpc.Internal; import io.grpc.ServerBuilder; import io.grpc.ServerStreamTracer; +import io.grpc.internal.AbstractServerImplBuilder; import io.grpc.internal.FixedObjectPool; import io.grpc.internal.GrpcUtil; import io.grpc.internal.InternalServer; @@ -72,7 +72,8 @@ * */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1783") -public final class InProcessServerBuilder extends ForwardingServerBuilder { +public final class InProcessServerBuilder extends + AbstractServerImplBuilder { /** * Create a server builder that will bind with the given name. * diff --git a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java new file mode 100644 index 00000000000..84a930e369f --- /dev/null +++ b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java @@ -0,0 +1,277 @@ +/* + * Copyright 2020 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.internal; + +import com.google.common.base.MoreObjects; +import io.grpc.BinaryLog; +import io.grpc.ClientInterceptor; +import io.grpc.CompressorRegistry; +import io.grpc.DecompressorRegistry; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.NameResolver; +import io.grpc.ProxyDetector; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +/** + * Temporarily duplicates {@link io.grpc.ForwardingChannelBuilder} to fix ABI backward + * compatibility. + * + * @param The concrete type of this builder. + * @see grpc/grpc-java#7211 + */ +public abstract class AbstractManagedChannelImplBuilder + > extends ManagedChannelBuilder { + + /** + * The default constructor. + */ + protected AbstractManagedChannelImplBuilder() {} + + /** + * This method serves to force sub classes to "hide" this static factory. + */ + public static ManagedChannelBuilder forAddress(String name, int port) { + throw new UnsupportedOperationException("Subclass failed to hide static factory"); + } + + /** + * This method serves to force sub classes to "hide" this static factory. + */ + public static ManagedChannelBuilder forTarget(String target) { + throw new UnsupportedOperationException("Subclass failed to hide static factory"); + } + + /** + * Returns the delegated {@code ManagedChannelBuilder}. + */ + protected abstract ManagedChannelBuilder delegate(); + + @Override + public T directExecutor() { + delegate().directExecutor(); + return thisT(); + } + + @Override + public T executor(Executor executor) { + delegate().executor(executor); + return thisT(); + } + + @Override + public T offloadExecutor(Executor executor) { + delegate().offloadExecutor(executor); + return thisT(); + } + + @Override + public T intercept(List interceptors) { + delegate().intercept(interceptors); + return thisT(); + } + + @Override + public T intercept(ClientInterceptor... interceptors) { + delegate().intercept(interceptors); + return thisT(); + } + + @Override + public T userAgent(String userAgent) { + delegate().userAgent(userAgent); + return thisT(); + } + + @Override + public T overrideAuthority(String authority) { + delegate().overrideAuthority(authority); + return thisT(); + } + + @Override + public T usePlaintext() { + delegate().usePlaintext(); + return thisT(); + } + + @Override + public T useTransportSecurity() { + delegate().useTransportSecurity(); + return thisT(); + } + + @Deprecated + @Override + public T nameResolverFactory(NameResolver.Factory resolverFactory) { + delegate().nameResolverFactory(resolverFactory); + return thisT(); + } + + @Override + public T defaultLoadBalancingPolicy(String policy) { + delegate().defaultLoadBalancingPolicy(policy); + return thisT(); + } + + @Override + public T enableFullStreamDecompression() { + delegate().enableFullStreamDecompression(); + return thisT(); + } + + @Override + public T decompressorRegistry(DecompressorRegistry registry) { + delegate().decompressorRegistry(registry); + return thisT(); + } + + @Override + public T compressorRegistry(CompressorRegistry registry) { + delegate().compressorRegistry(registry); + return thisT(); + } + + @Override + public T idleTimeout(long value, TimeUnit unit) { + delegate().idleTimeout(value, unit); + return thisT(); + } + + @Override + public T maxInboundMessageSize(int max) { + delegate().maxInboundMessageSize(max); + return thisT(); + } + + @Override + public T maxInboundMetadataSize(int max) { + delegate().maxInboundMetadataSize(max); + return thisT(); + } + + @Override + public T keepAliveTime(long keepAliveTime, TimeUnit timeUnit) { + delegate().keepAliveTime(keepAliveTime, timeUnit); + return thisT(); + } + + @Override + public T keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit) { + delegate().keepAliveTimeout(keepAliveTimeout, timeUnit); + return thisT(); + } + + @Override + public T keepAliveWithoutCalls(boolean enable) { + delegate().keepAliveWithoutCalls(enable); + return thisT(); + } + + @Override + public T maxRetryAttempts(int maxRetryAttempts) { + delegate().maxRetryAttempts(maxRetryAttempts); + return thisT(); + } + + @Override + public T maxHedgedAttempts(int maxHedgedAttempts) { + delegate().maxHedgedAttempts(maxHedgedAttempts); + return thisT(); + } + + @Override + public T retryBufferSize(long bytes) { + delegate().retryBufferSize(bytes); + return thisT(); + } + + @Override + public T perRpcBufferLimit(long bytes) { + delegate().perRpcBufferLimit(bytes); + return thisT(); + } + + @Override + public T disableRetry() { + delegate().disableRetry(); + return thisT(); + } + + @Override + public T enableRetry() { + delegate().enableRetry(); + return thisT(); + } + + @Override + public T setBinaryLog(BinaryLog binaryLog) { + delegate().setBinaryLog(binaryLog); + return thisT(); + } + + @Override + public T maxTraceEvents(int maxTraceEvents) { + delegate().maxTraceEvents(maxTraceEvents); + return thisT(); + } + + @Override + public T proxyDetector(ProxyDetector proxyDetector) { + delegate().proxyDetector(proxyDetector); + return thisT(); + } + + @Override + public T defaultServiceConfig(@Nullable Map serviceConfig) { + delegate().defaultServiceConfig(serviceConfig); + return thisT(); + } + + @Override + public T disableServiceConfigLookUp() { + delegate().disableServiceConfigLookUp(); + return thisT(); + } + + /** + * Returns the {@link ManagedChannel} built by the delegate by default. Overriding method can + * return different value. + */ + @Override + public ManagedChannel build() { + return delegate().build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("delegate", delegate()).toString(); + } + + /** + * Returns the correctly typed version of the builder. + */ + protected final T thisT() { + @SuppressWarnings("unchecked") + T thisT = (T) this; + return thisT; + } +} diff --git a/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java new file mode 100644 index 00000000000..715161c0635 --- /dev/null +++ b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java @@ -0,0 +1,182 @@ +/* + * Copyright 2020 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.internal; + +import com.google.common.base.MoreObjects; +import io.grpc.BinaryLog; +import io.grpc.BindableService; +import io.grpc.CompressorRegistry; +import io.grpc.DecompressorRegistry; +import io.grpc.HandlerRegistry; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptor; +import io.grpc.ServerServiceDefinition; +import io.grpc.ServerStreamTracer; +import io.grpc.ServerTransportFilter; +import java.io.File; +import java.io.InputStream; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +/** + * A {@link ServerBuilder} that delegates all its builder method to another builder by default. + * + *

Temporarily duplicates io.grpc.ForwardingServerBuilder (temporarily package-private) + * to fix ABI backward compatibility. + + * @param The concrete type of this builder. + * @see grpc/grpc-java#7211 + */ +public abstract class AbstractServerImplBuilder + > extends ServerBuilder { + + /** The default constructor. */ + protected AbstractServerImplBuilder() {} + + /** + * This method serves to force sub classes to "hide" this static factory. + */ + public static ServerBuilder forPort(int port) { + throw new UnsupportedOperationException("Subclass failed to hide static factory"); + } + + /** + * Returns the delegated {@code ServerBuilder}. + */ + protected abstract ServerBuilder delegate(); + + @Override + public T directExecutor() { + delegate().directExecutor(); + return thisT(); + } + + @Override + public T executor(@Nullable Executor executor) { + delegate().executor(executor); + return thisT(); + } + + @Override + public T addService(ServerServiceDefinition service) { + delegate().addService(service); + return thisT(); + } + + @Override + public T addService(BindableService bindableService) { + delegate().addService(bindableService); + return thisT(); + } + + @Override + public T intercept(ServerInterceptor interceptor) { + delegate().intercept(interceptor); + return thisT(); + } + + @Override + public T addTransportFilter(ServerTransportFilter filter) { + delegate().addTransportFilter(filter); + return thisT(); + } + + @Override + public T addStreamTracerFactory(ServerStreamTracer.Factory factory) { + delegate().addStreamTracerFactory(factory); + return thisT(); + } + + @Override + public T fallbackHandlerRegistry(@Nullable HandlerRegistry fallbackRegistry) { + delegate().fallbackHandlerRegistry(fallbackRegistry); + return thisT(); + } + + @Override + public T useTransportSecurity(File certChain, File privateKey) { + delegate().useTransportSecurity(certChain, privateKey); + return thisT(); + } + + @Override + public T useTransportSecurity(InputStream certChain, InputStream privateKey) { + delegate().useTransportSecurity(certChain, privateKey); + return thisT(); + } + + @Override + public T decompressorRegistry(@Nullable DecompressorRegistry registry) { + delegate().decompressorRegistry(registry); + return thisT(); + } + + @Override + public T compressorRegistry(@Nullable CompressorRegistry registry) { + delegate().compressorRegistry(registry); + return thisT(); + } + + @Override + public T handshakeTimeout(long timeout, TimeUnit unit) { + delegate().handshakeTimeout(timeout, unit); + return thisT(); + } + + @Override + public T maxInboundMessageSize(int bytes) { + delegate().maxInboundMessageSize(bytes); + return thisT(); + } + + @Override + public T maxInboundMetadataSize(int bytes) { + delegate().maxInboundMetadataSize(bytes); + return thisT(); + } + + @Override + public T setBinaryLog(BinaryLog binaryLog) { + delegate().setBinaryLog(binaryLog); + return thisT(); + } + + /** + * Returns the {@link Server} built by the delegate by default. Overriding method can return + * different value. + */ + @Override + public Server build() { + return delegate().build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("delegate", delegate()).toString(); + } + + /** + * Returns the correctly typed version of the builder. + */ + protected final T thisT() { + @SuppressWarnings("unchecked") + T thisT = (T) this; + return thisT; + } +} diff --git a/core/src/main/java/io/grpc/internal/ClientCallImpl.java b/core/src/main/java/io/grpc/internal/ClientCallImpl.java index 3c3a2227780..86ec0575adf 100644 --- a/core/src/main/java/io/grpc/internal/ClientCallImpl.java +++ b/core/src/main/java/io/grpc/internal/ClientCallImpl.java @@ -54,6 +54,7 @@ import io.perfmark.Tag; import java.io.InputStream; import java.nio.charset.Charset; +import java.util.Locale; import java.util.concurrent.CancellationException; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; @@ -441,7 +442,7 @@ public void run() { buf.append('-'); } buf.append(seconds); - buf.append(String.format(".%09d", nanos)); + buf.append(String.format(Locale.US, ".%09d", nanos)); buf.append("s. "); buf.append(insight); stream.cancel(DEADLINE_EXCEEDED.augmentDescription(buf.toString())); diff --git a/core/src/main/java/io/grpc/internal/DelayedClientCall.java b/core/src/main/java/io/grpc/internal/DelayedClientCall.java index c3d3823ed11..41f672af347 100644 --- a/core/src/main/java/io/grpc/internal/DelayedClientCall.java +++ b/core/src/main/java/io/grpc/internal/DelayedClientCall.java @@ -30,6 +30,7 @@ import io.grpc.Status; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -117,7 +118,7 @@ private ScheduledFuture scheduleDeadlineIfNeeded( buf.append("Deadline exceeded after "); } buf.append(seconds); - buf.append(String.format(".%09d", nanos)); + buf.append(String.format(Locale.US, ".%09d", nanos)); buf.append("s. "); /** Cancels the call if deadline exceeded prior to the real call being set. */ class DeadlineExceededRunnable implements Runnable { diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index ce46d8c9bf5..2a51fd165e8 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -197,7 +197,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - private static final String IMPLEMENTATION_VERSION = "1.33.0"; // CURRENT_GRPC_VERSION + private static final String IMPLEMENTATION_VERSION = "1.33.1"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java new file mode 100644 index 00000000000..8643165eec6 --- /dev/null +++ b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2020 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.internal; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import com.google.common.base.Defaults; +import io.grpc.ForwardingTestUtil; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link AbstractManagedChannelImplBuilder}. + */ +@RunWith(JUnit4.class) +public class AbstractManagedChannelImplBuilderTest { + private final ManagedChannelBuilder mockDelegate = mock(ManagedChannelBuilder.class); + + private final AbstractManagedChannelImplBuilder testChannelBuilder = new TestBuilder(); + + private final class TestBuilder extends AbstractManagedChannelImplBuilder { + @Override + protected ManagedChannelBuilder delegate() { + return mockDelegate; + } + } + + @Test + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + ManagedChannelBuilder.class, + mockDelegate, + testChannelBuilder, + Collections.emptyList(), + new ForwardingTestUtil.ArgumentProvider() { + @Override + public Object get(Method method, int argPos, Class clazz) { + if (method.getName().equals("maxInboundMetadataSize")) { + assertThat(argPos).isEqualTo(0); + return 1; // an arbitrary positive number + } + return null; + } + }); + } + + @Test + public void allBuilderMethodsReturnThis() throws Exception { + for (Method method : ManagedChannelBuilder.class.getDeclaredMethods()) { + if (Modifier.isStatic(method.getModifiers()) || Modifier.isPrivate(method.getModifiers())) { + continue; + } + if (method.getName().equals("build")) { + continue; + } + Class[] argTypes = method.getParameterTypes(); + Object[] args = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + args[i] = Defaults.defaultValue(argTypes[i]); + } + if (method.getName().equals("maxInboundMetadataSize")) { + args[0] = 1; // an arbitrary positive number + } + + Object returnedValue = method.invoke(testChannelBuilder, args); + + assertThat(returnedValue).isSameInstanceAs(testChannelBuilder); + } + } + + @Test + public void buildReturnsDelegateBuildByDefault() { + ManagedChannel mockChannel = mock(ManagedChannel.class); + doReturn(mockChannel).when(mockDelegate).build(); + + assertThat(testChannelBuilder.build()).isSameInstanceAs(mockChannel); + } +} diff --git a/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java new file mode 100644 index 00000000000..9f6859a8420 --- /dev/null +++ b/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2020 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.internal; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import com.google.common.base.Defaults; +import io.grpc.ForwardingTestUtil; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link AbstractServerImplBuilderTest}. + */ +@RunWith(JUnit4.class) +public class AbstractServerImplBuilderTest { + private final ServerBuilder mockDelegate = mock(ServerBuilder.class); + + private final AbstractServerImplBuilder testServerBuilder = new TestBuilder(); + + private final class TestBuilder extends AbstractServerImplBuilder { + @Override + protected ServerBuilder delegate() { + return mockDelegate; + } + } + + @Test + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + ServerBuilder.class, + mockDelegate, + testServerBuilder, + Collections.emptyList()); + } + + @Test + public void allBuilderMethodsReturnThis() throws Exception { + for (Method method : ServerBuilder.class.getDeclaredMethods()) { + if (Modifier.isStatic(method.getModifiers()) || Modifier.isPrivate(method.getModifiers())) { + continue; + } + if (method.getName().equals("build")) { + continue; + } + Class[] argTypes = method.getParameterTypes(); + Object[] args = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + args[i] = Defaults.defaultValue(argTypes[i]); + } + + Object returnedValue = method.invoke(testServerBuilder, args); + + assertThat(returnedValue).isSameInstanceAs(testServerBuilder); + } + } + + @Test + public void buildReturnsDelegateBuildByDefault() { + Server server = mock(Server.class); + doReturn(server).when(mockDelegate).build(); + + assertThat(testServerBuilder.build()).isSameInstanceAs(server); + } +} diff --git a/cronet/README.md b/cronet/README.md index 530fbea71b0..9132af622c4 100644 --- a/cronet/README.md +++ b/cronet/README.md @@ -26,7 +26,7 @@ In your app module's `build.gradle` file, include a dependency on both `grpc-cro Google Play Services Client Library for Cronet ``` -implementation 'io.grpc:grpc-cronet:1.33.0' +implementation 'io.grpc:grpc-cronet:1.33.1' implementation 'com.google.android.gms:play-services-cronet:16.0.0' ``` diff --git a/cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java b/cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java index 3ed71e234aa..68182421333 100644 --- a/cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java +++ b/cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java @@ -26,9 +26,9 @@ import com.google.common.util.concurrent.MoreExecutors; import io.grpc.ChannelLogger; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingChannelBuilder; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.internal.AbstractManagedChannelImplBuilder; import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ConnectionClientTransport; import io.grpc.internal.GrpcUtil; @@ -50,7 +50,8 @@ /** Convenience class for building channels with the cronet transport. */ @ExperimentalApi("There is no plan to make this API stable, given transport API instability") -public final class CronetChannelBuilder extends ForwardingChannelBuilder { +public final class CronetChannelBuilder + extends AbstractManagedChannelImplBuilder { private static final String LOG_TAG = "CronetChannelBuilder"; diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md index b152c9286a0..a84d9a32652 100644 --- a/documentation/android-channel-builder.md +++ b/documentation/android-channel-builder.md @@ -36,8 +36,8 @@ In your `build.gradle` file, include a dependency on both `grpc-android` and `grpc-okhttp`: ``` -implementation 'io.grpc:grpc-android:1.33.0' -implementation 'io.grpc:grpc-okhttp:1.33.0' +implementation 'io.grpc:grpc-android:1.33.1' +implementation 'io.grpc:grpc-okhttp:1.33.1' ``` You also need permission to access the device's network state in your diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 6ae625419a6..c972b4df3f3 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -30,7 +30,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.12.0' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -50,12 +50,12 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.33.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.33.1' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' testImplementation 'junit:junit:4.12' testImplementation 'com.google.truth:truth:1.0.1' - testImplementation 'io.grpc:grpc-testing:1.33.0' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.33.1' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 5211c63b6c1..20cb76bc97d 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -28,7 +28,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.12.0' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -48,8 +48,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.33.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.33.1' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index c0621d62bc4..f4e814f873f 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -28,7 +28,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.12.0' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -48,8 +48,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.33.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.33.1' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index 7dee456fb1f..2ce7202745d 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -29,7 +29,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.12.0' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.0' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -49,8 +49,8 @@ dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.33.0' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.33.0' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.33.1' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/build.gradle b/examples/build.gradle index 4b6c733151e..bc976de708a 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def protobufVersion = '3.12.0' def protocVersion = protobufVersion diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index e01598187f3..3fde646e060 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def protocVersion = '3.12.0' dependencies { diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 6542df94351..9037f82987e 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def protobufVersion = '3.12.0' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index a255df8a0dd..dd1a08fee8a 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.33.0 + 1.33.1 example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.33.0 + 1.33.1 3.12.0 1.7 diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index f7f44ab430e..d621bb5201e 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -21,7 +21,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def protobufVersion = '3.12.0' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index a01948f90ce..b5ec5a12681 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.33.0 + 1.33.1 example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.33.0 + 1.33.1 3.12.0 1.7 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index d827dcdf017..1ec1d0bef61 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -22,7 +22,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def protobufVersion = '3.12.0' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index c6064be0a00..c6d1d62d2ba 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.33.0 + 1.33.1 example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.33.0 + 1.33.1 3.12.0 3.12.0 diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 1fb5859bdca..75a22fab856 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -23,7 +23,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION def nettyTcNativeVersion = '2.0.31.Final' def protocVersion = '3.12.0' diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index 08f948edf94..e223fbfb162 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.33.0 + 1.33.1 example-tls https://github.com/grpc/grpc-java UTF-8 - 1.33.0 + 1.33.1 3.12.0 2.0.31.Final diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index ccb3a68803c..54484e22023 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -18,7 +18,7 @@ targetCompatibility = 1.7 // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.33.0' // CURRENT_GRPC_VERSION +def grpcVersion = '1.33.1' // CURRENT_GRPC_VERSION dependencies { // This example's client is the same as the helloworld client. We depend on the helloworld diff --git a/examples/pom.xml b/examples/pom.xml index e7d66e501c6..2fc62b0e8e4 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.33.0 + 1.33.1 examples https://github.com/grpc/grpc-java UTF-8 - 1.33.0 + 1.33.1 3.12.0 3.12.0 diff --git a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java index 9757cbb3f98..4b5de5963f8 100644 --- a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java +++ b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java @@ -28,10 +28,10 @@ import io.grpc.ChannelLogger; import io.grpc.EquivalentAddressGroup; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingChannelBuilder; import io.grpc.HttpConnectProxiedSocketAddress; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.internal.AbstractManagedChannelImplBuilder; import io.grpc.internal.AtomicBackoff; import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ConnectionClientTransport; @@ -67,7 +67,8 @@ */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784") @CanIgnoreReturnValue -public final class NettyChannelBuilder extends ForwardingChannelBuilder { +public final class NettyChannelBuilder extends + AbstractManagedChannelImplBuilder { // 1MiB. public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1024 * 1024; diff --git a/netty/src/main/java/io/grpc/netty/NettyClientHandler.java b/netty/src/main/java/io/grpc/netty/NettyClientHandler.java index 61052bd190c..631d9e81863 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientHandler.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientHandler.java @@ -129,6 +129,7 @@ protected void handleNotInUse() { private Http2Ping ping; private Attributes attributes; private InternalChannelz.Security securityInfo; + private Status abruptGoAwayStatus; static NettyClientHandler newHandler( ClientTransportLifecycleManager lifecycleManager, @@ -556,6 +557,21 @@ private void createStream(CreateStreamCommand command, ChannelPromise promise) } return; } + if (connection().goAwayReceived() + && streamId > connection().local().lastStreamKnownByPeer()) { + // This should only be reachable during onGoAwayReceived, as otherwise + // getShutdownThrowable() != null + command.stream().setNonExistent(); + Status s = abruptGoAwayStatus; + if (s == null) { + // Should be impossible, but handle psuedo-gracefully + s = Status.INTERNAL.withDescription( + "Failed due to abrupt GOAWAY, but can't find GOAWAY details"); + } + command.stream().transportReportStatus(s, RpcProgress.REFUSED, true, new Metadata()); + promise.setFailure(s.asRuntimeException()); + return; + } NettyClientStream.TransportState stream = command.stream(); Http2Headers headers = command.headers(); @@ -772,6 +788,7 @@ public boolean visit(Http2Stream stream) throws Http2Exception { */ private void goingAway(Status status) { lifecycleManager.notifyGracefulShutdown(status); + abruptGoAwayStatus = status; // Try to allocate as many in-flight streams as possible, to reduce race window of // https://github.com/grpc/grpc-java/issues/2562 . To be of any help, the server has to // gracefully shut down the connection with two GOAWAYs. gRPC servers generally send a PING diff --git a/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java b/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java index 8bda3d7c91e..520e3bfbd9a 100644 --- a/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java +++ b/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java @@ -27,10 +27,10 @@ import com.google.common.annotations.VisibleForTesting; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingServerBuilder; import io.grpc.Internal; import io.grpc.ServerBuilder; import io.grpc.ServerStreamTracer; +import io.grpc.internal.AbstractServerImplBuilder; import io.grpc.internal.FixedObjectPool; import io.grpc.internal.GrpcUtil; import io.grpc.internal.InternalServer; @@ -66,7 +66,7 @@ */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784") @CanIgnoreReturnValue -public final class NettyServerBuilder extends ForwardingServerBuilder { +public final class NettyServerBuilder extends AbstractServerImplBuilder { // 1MiB public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1024 * 1024; diff --git a/netty/src/test/java/io/grpc/netty/NettyClientHandlerTest.java b/netty/src/test/java/io/grpc/netty/NettyClientHandlerTest.java index 0ff2d981410..4e469e707bf 100644 --- a/netty/src/test/java/io/grpc/netty/NettyClientHandlerTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyClientHandlerTest.java @@ -375,6 +375,23 @@ public void receivedGoAwayShouldNotAffectRacingQueuedStreamId() throws Exception assertTrue(future.isDone()); } + @Test + public void receivedAbruptGoAwayShouldFailRacingQueuedStreamid() throws Exception { + // This command has not actually been executed yet + ChannelFuture future = writeQueue().enqueue( + newCreateStreamCommand(grpcHeaders, streamTransportState), true); + // Read a GOAWAY that indicates our stream can't be sent + channelRead(goAwayFrame(0, 8 /* Cancel */, Unpooled.copiedBuffer("this is a test", UTF_8))); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Status.class); + verify(streamListener).closed(captor.capture(), same(REFUSED), + ArgumentMatchers.notNull()); + assertEquals(Status.CANCELLED.getCode(), captor.getValue().getCode()); + assertEquals("HTTP/2 error code: CANCEL\nReceived Goaway\nthis is a test", + captor.getValue().getDescription()); + assertTrue(future.isDone()); + } + @Test public void receivedResetWithRefuseCode() throws Exception { ChannelFuture future = enqueue(newCreateStreamCommand(grpcHeaders, streamTransportState)); diff --git a/okhttp/build.gradle b/okhttp/build.gradle index 0c23c3b9f80..5b2f1a13e35 100644 --- a/okhttp/build.gradle +++ b/okhttp/build.gradle @@ -34,8 +34,11 @@ project.sourceSets { checkstyleMain.exclude '**/io/grpc/okhttp/internal/**' -javadoc.exclude 'io/grpc/okhttp/internal/**' -javadoc.options.links 'http://square.github.io/okhttp/2.x/okhttp/' +javadoc { + options.links 'http://square.github.io/okhttp/2.x/okhttp/' + exclude 'io/grpc/okhttp/Internal*' + exclude 'io/grpc/okhttp/internal/**' +} jacocoTestReport { classDirectories.from = sourceSets.main.output.collect { diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index 93ea57e2df4..05cb2fea8be 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -24,9 +24,9 @@ import com.google.common.base.Preconditions; import io.grpc.ChannelLogger; import io.grpc.ExperimentalApi; -import io.grpc.ForwardingChannelBuilder; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.internal.AbstractManagedChannelImplBuilder; import io.grpc.internal.AtomicBackoff; import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ConnectionClientTransport; @@ -58,7 +58,8 @@ /** Convenience class for building channels with the OkHttp transport. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1785") -public final class OkHttpChannelBuilder extends ForwardingChannelBuilder { +public final class OkHttpChannelBuilder extends + AbstractManagedChannelImplBuilder { public static final int DEFAULT_FLOW_CONTROL_WINDOW = 65535; private final ManagedChannelImplBuilder managedChannelImplBuilder;