next) {
+ numInterceptedCalls += 1;
+ return next.startCall(call, headers);
+ }
+ }
}
diff --git a/binder/src/main/java/io/grpc/binder/AndroidComponentAddress.java b/binder/src/main/java/io/grpc/binder/AndroidComponentAddress.java
index cb4f7f794cf..90197ee8382 100644
--- a/binder/src/main/java/io/grpc/binder/AndroidComponentAddress.java
+++ b/binder/src/main/java/io/grpc/binder/AndroidComponentAddress.java
@@ -22,7 +22,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import io.grpc.ExperimentalApi;
import java.net.SocketAddress;
/**
@@ -41,8 +40,7 @@
* fields, namely, an action of {@link ApiConstants#ACTION_BIND}, an empty category set and null
* type and data URI.
*/
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
-public class AndroidComponentAddress extends SocketAddress { // NOTE: Only temporarily non-final.
+public final class AndroidComponentAddress extends SocketAddress {
private static final long serialVersionUID = 0L;
private final Intent bindIntent; // An "explicit" Intent. In other words, getComponent() != null.
@@ -103,6 +101,11 @@ public static AndroidComponentAddress forComponent(ComponentName component) {
new Intent(ApiConstants.ACTION_BIND).setComponent(component));
}
+ /**
+ * Returns the Authority which is the package name of the target app.
+ *
+ * See {@link android.content.ComponentName}.
+ */
public String getAuthority() {
return getComponent().getPackageName();
}
diff --git a/binder/src/main/java/io/grpc/binder/BinderChannelBuilder.java b/binder/src/main/java/io/grpc/binder/BinderChannelBuilder.java
index 91e4e8f1c76..214eb6dc4c5 100644
--- a/binder/src/main/java/io/grpc/binder/BinderChannelBuilder.java
+++ b/binder/src/main/java/io/grpc/binder/BinderChannelBuilder.java
@@ -17,16 +17,13 @@
package io.grpc.binder;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
-import android.app.Application;
-import android.content.ComponentName;
import android.content.Context;
import androidx.core.content.ContextCompat;
import com.google.errorprone.annotations.DoNotCall;
import io.grpc.ChannelCredentials;
import io.grpc.ChannelLogger;
-import io.grpc.CompressorRegistry;
-import io.grpc.DecompressorRegistry;
import io.grpc.ExperimentalApi;
import io.grpc.ForwardingChannelBuilder;
import io.grpc.ManagedChannel;
@@ -124,6 +121,7 @@ public static BinderChannelBuilder forTarget(String target) {
private SecurityPolicy securityPolicy;
private InboundParcelablePolicy inboundParcelablePolicy;
private BindServiceFlags bindServiceFlags;
+ private boolean strictLifecycleManagement;
private BinderChannelBuilder(
@Nullable AndroidComponentAddress directAddress,
@@ -164,6 +162,7 @@ public ClientTransportFactory buildClientTransportFactory() {
new BinderChannelTransportFactoryBuilder(),
null);
}
+ idleTimeout(60, TimeUnit.SECONDS);
}
@Override
@@ -224,6 +223,25 @@ public BinderChannelBuilder inboundParcelablePolicy(
return this;
}
+ /**
+ * Disables the channel idle timeout and prevents it from being enabled. This
+ * allows a centralized application method to configure the channel builder
+ * and return it, without worrying about another part of the application
+ * accidentally enabling the idle timeout.
+ */
+ public BinderChannelBuilder strictLifecycleManagement() {
+ strictLifecycleManagement = true;
+ super.idleTimeout(1000, TimeUnit.DAYS); // >30 days disables timeouts entirely.
+ return this;
+ }
+
+ @Override
+ public BinderChannelBuilder idleTimeout(long value, TimeUnit unit) {
+ checkState(!strictLifecycleManagement, "Idle timeouts are not supported when strict lifecycle management is enabled");
+ super.idleTimeout(value, unit);
+ return this;
+ }
+
/** Creates new binder transports. */
private static final class TransportFactory implements ClientTransportFactory {
private final Context sourceContext;
diff --git a/binder/src/main/java/io/grpc/binder/BinderInternal.java b/binder/src/main/java/io/grpc/binder/BinderInternal.java
new file mode 100644
index 00000000000..34f7793714f
--- /dev/null
+++ b/binder/src/main/java/io/grpc/binder/BinderInternal.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2022 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.binder;
+
+import android.os.IBinder;
+import io.grpc.Internal;
+
+/**
+ * Helper class to expose IBinderReceiver methods for legacy internal builders.
+ */
+@Internal
+public class BinderInternal {
+
+ /**
+ * Sets the receiver's {@link IBinder} using {@link IBinderReceiver#set(IBinder)}.
+ */
+ public static void setIBinder(IBinderReceiver receiver, IBinder binder) {
+ receiver.set(binder);
+ }
+}
diff --git a/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java b/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java
index 383bd3f8e49..eaa94bffc45 100644
--- a/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java
+++ b/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java
@@ -21,34 +21,24 @@
import android.app.Service;
import android.os.IBinder;
-import com.google.common.base.Supplier;
import com.google.errorprone.annotations.DoNotCall;
-import io.grpc.CompressorRegistry;
-import io.grpc.DecompressorRegistry;
import io.grpc.ExperimentalApi;
import io.grpc.Server;
import io.grpc.ServerBuilder;
-import io.grpc.ServerStreamTracer;
import io.grpc.binder.internal.BinderServer;
import io.grpc.binder.internal.BinderTransportSecurity;
import io.grpc.ForwardingServerBuilder;
import io.grpc.internal.FixedObjectPool;
import io.grpc.internal.GrpcUtil;
-import io.grpc.internal.InternalServer;
import io.grpc.internal.ServerImplBuilder;
-import io.grpc.internal.ServerImplBuilder.ClientTransportServersBuilder;
import io.grpc.internal.ObjectPool;
import io.grpc.internal.SharedResourcePool;
import java.io.File;
-import java.io.IOException;
-import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
-import javax.annotation.Nullable;
/**
* Builder for a server that services requests from an Android Service.
*/
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class BinderServerBuilder
extends ForwardingServerBuilder {
@@ -81,6 +71,7 @@ public static BinderServerBuilder forPort(int port) {
SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE);
private ServerSecurityPolicy securityPolicy;
private InboundParcelablePolicy inboundParcelablePolicy;
+ private boolean isBuilt;
private BinderServerBuilder(
AndroidComponentAddress listenAddress,
@@ -95,20 +86,13 @@ private BinderServerBuilder(
streamTracerFactories,
securityPolicy,
inboundParcelablePolicy);
- binderReceiver.set(server.getHostBinder());
+ BinderInternal.setIBinder(binderReceiver, server.getHostBinder());
return server;
});
- // Disable compression by default, since there's little benefit when all communication is
- // on-device, and it means sending supported-encoding headers with every call.
- decompressorRegistry(DecompressorRegistry.emptyInstance());
- compressorRegistry(CompressorRegistry.newEmptyInstance());
-
// Disable stats and tracing by default.
serverImplBuilder.setStatsEnabled(false);
serverImplBuilder.setTracingEnabled(false);
-
- BinderTransportSecurity.installAuthInterceptor(this);
}
@Override
@@ -117,12 +101,14 @@ protected ServerBuilder> delegate() {
}
/** Enable stats collection using census. */
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public BinderServerBuilder enableStats() {
serverImplBuilder.setStatsEnabled(true);
return this;
}
/** Enable tracing using census. */
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public BinderServerBuilder enableTracing() {
serverImplBuilder.setTracingEnabled(true);
return this;
@@ -157,12 +143,16 @@ public BinderServerBuilder securityPolicy(ServerSecurityPolicy securityPolicy) {
}
/** Sets the policy for inbound parcelable objects. */
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public BinderServerBuilder inboundParcelablePolicy(
InboundParcelablePolicy inboundParcelablePolicy) {
this.inboundParcelablePolicy = checkNotNull(inboundParcelablePolicy, "inboundParcelablePolicy");
return this;
}
+ /**
+ * Always fails. TLS is not supported in BinderServer.
+ */
@Override
public BinderServerBuilder useTransportSecurity(File certChain, File privateKey) {
throw new UnsupportedOperationException("TLS not supported in BinderServer");
@@ -177,6 +167,11 @@ public BinderServerBuilder useTransportSecurity(File certChain, File privateKey)
*/
@Override // For javadoc refinement only.
public Server build() {
+ // Since we install a final interceptor here, we need to ensure we're only built once.
+ checkState(!isBuilt, "BinderServerBuilder can only be used to build one server instance.");
+ isBuilt = true;
+ // We install the security interceptor last, so it's closest to the transport.
+ BinderTransportSecurity.installAuthInterceptor(this);
return super.build();
}
}
diff --git a/binder/src/main/java/io/grpc/binder/IBinderReceiver.java b/binder/src/main/java/io/grpc/binder/IBinderReceiver.java
index bd8e1f50af9..adf4a0d3d8e 100644
--- a/binder/src/main/java/io/grpc/binder/IBinderReceiver.java
+++ b/binder/src/main/java/io/grpc/binder/IBinderReceiver.java
@@ -17,24 +17,22 @@
package io.grpc.binder;
import android.os.IBinder;
-import io.grpc.ExperimentalApi;
import javax.annotation.Nullable;
/** A container for at most one instance of {@link IBinder}, useful as an "out parameter". */
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class IBinderReceiver {
- @Nullable private IBinder value;
+ @Nullable private volatile IBinder value;
/** Constructs a new, initially empty, container. */
public IBinderReceiver() {}
/** Returns the contents of this container or null if it is empty. */
@Nullable
- public synchronized IBinder get() {
+ public IBinder get() {
return value;
}
- public synchronized void set(IBinder value) {
+ protected void set(IBinder value) {
this.value = value;
}
}
diff --git a/binder/src/main/java/io/grpc/binder/ParcelableUtils.java b/binder/src/main/java/io/grpc/binder/ParcelableUtils.java
index 164de7de8b8..969344ea68d 100644
--- a/binder/src/main/java/io/grpc/binder/ParcelableUtils.java
+++ b/binder/src/main/java/io/grpc/binder/ParcelableUtils.java
@@ -17,7 +17,6 @@
package io.grpc.binder;
import android.os.Parcelable;
-import io.grpc.ExperimentalApi;
import io.grpc.Metadata;
import io.grpc.binder.internal.MetadataHelper;
@@ -26,7 +25,6 @@
*
* This class models the same pattern as the {@code ProtoLiteUtils} class.
*/
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class ParcelableUtils {
private ParcelableUtils() {}
diff --git a/binder/src/main/java/io/grpc/binder/SecurityPolicies.java b/binder/src/main/java/io/grpc/binder/SecurityPolicies.java
index 653ae90bd77..1a31ef823d3 100644
--- a/binder/src/main/java/io/grpc/binder/SecurityPolicies.java
+++ b/binder/src/main/java/io/grpc/binder/SecurityPolicies.java
@@ -42,7 +42,6 @@
/** Static factory methods for creating standard security policies. */
@CheckReturnValue
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class SecurityPolicies {
private static final int MY_UID = Process.myUid();
@@ -50,10 +49,15 @@ public final class SecurityPolicies {
private SecurityPolicies() {}
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static ServerSecurityPolicy serverInternalOnly() {
return new ServerSecurityPolicy();
}
+ /**
+ * Creates a default {@link SecurityPolicy} that allows access only to callers with the same UID
+ * as the current process.
+ */
public static SecurityPolicy internalOnly() {
return new SecurityPolicy() {
@Override
@@ -66,6 +70,7 @@ public Status checkAuthorization(int uid) {
};
}
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy permissionDenied(String description) {
Status denied = Status.PERMISSION_DENIED.withDescription(description);
return new SecurityPolicy() {
@@ -84,6 +89,7 @@ public Status checkAuthorization(int uid) {
* @param requiredSignature the allowed signature of the allowed package.
* @throws NullPointerException if any of the inputs are {@code null}.
*/
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy hasSignature(
PackageManager packageManager, String packageName, Signature requiredSignature) {
return oneOfSignatures(
@@ -99,6 +105,7 @@ public static SecurityPolicy hasSignature(
* @throws NullPointerException if any of the inputs are {@code null}.
* @throws IllegalArgumentException if {@code requiredSignatureSha256Hash} is not of length 32.
*/
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy hasSignatureSha256Hash(
PackageManager packageManager, String packageName, byte[] requiredSignatureSha256Hash) {
return oneOfSignatureSha256Hash(
@@ -114,6 +121,7 @@ public static SecurityPolicy hasSignatureSha256Hash(
* @throws NullPointerException if any of the inputs are {@code null}.
* @throws IllegalArgumentException if {@code requiredSignatures} is empty.
*/
+ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static SecurityPolicy oneOfSignatures(
PackageManager packageManager,
String packageName,
diff --git a/binder/src/main/java/io/grpc/binder/SecurityPolicy.java b/binder/src/main/java/io/grpc/binder/SecurityPolicy.java
index d13f3a863fd..6b0fb40310a 100644
--- a/binder/src/main/java/io/grpc/binder/SecurityPolicy.java
+++ b/binder/src/main/java/io/grpc/binder/SecurityPolicy.java
@@ -16,7 +16,6 @@
package io.grpc.binder;
-import io.grpc.ExperimentalApi;
import io.grpc.Status;
import javax.annotation.CheckReturnValue;
@@ -37,7 +36,6 @@
* re-installation of the applications involved.
*/
@CheckReturnValue
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public abstract class SecurityPolicy {
protected SecurityPolicy() {}
diff --git a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java
index 46a124e1f47..d91a487a57c 100644
--- a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java
+++ b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java
@@ -17,7 +17,6 @@
package io.grpc.binder;
import com.google.common.collect.ImmutableMap;
-import io.grpc.ExperimentalApi;
import io.grpc.Status;
import java.util.HashMap;
import java.util.Map;
@@ -28,7 +27,6 @@
*
* Contains a default policy, and optional policies for each server.
*/
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public final class ServerSecurityPolicy {
private final SecurityPolicy defaultPolicy;
diff --git a/binder/src/test/java/io/grpc/binder/BinderChannelBuilderTest.java b/binder/src/test/java/io/grpc/binder/BinderChannelBuilderTest.java
new file mode 100644
index 00000000000..5dd7e13107e
--- /dev/null
+++ b/binder/src/test/java/io/grpc/binder/BinderChannelBuilderTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.binder;
+
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import androidx.test.core.app.ApplicationProvider;
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public final class BinderChannelBuilderTest {
+ private final Context appContext = ApplicationProvider.getApplicationContext();
+ private final AndroidComponentAddress addr = AndroidComponentAddress.forContext(appContext);
+
+ @Test
+ public void strictLifecycleManagementForbidsIdleTimers() {
+ BinderChannelBuilder builder = BinderChannelBuilder.forAddress(addr, appContext);
+ builder.strictLifecycleManagement();
+ try {
+ builder.idleTimeout(10, TimeUnit.SECONDS);
+ fail();
+ } catch (IllegalStateException ise) {
+ // Expected.
+ }
+ }
+}
diff --git a/build.gradle b/build.gradle
index 21068ba522d..04ab724a2e3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,7 +20,7 @@ subprojects {
apply plugin: "net.ltgt.errorprone"
group = "io.grpc"
- version = "1.51.0-SNAPSHOT" // CURRENT_GRPC_VERSION
+ version = "1.52.0" // CURRENT_GRPC_VERSION
repositories {
maven { // The google mirror is less flaky than mavenCentral()
diff --git a/census/src/main/java/io/grpc/census/CensusStatsModule.java b/census/src/main/java/io/grpc/census/CensusStatsModule.java
index d05368f3ee5..03eaf73570d 100644
--- a/census/src/main/java/io/grpc/census/CensusStatsModule.java
+++ b/census/src/main/java/io/grpc/census/CensusStatsModule.java
@@ -751,10 +751,7 @@ public void streamClosed(Status status) {
@Override
public Context filterContext(Context context) {
- if (!module.tagger.empty().equals(parentCtx)) {
- return ContextUtils.withValue(context, parentCtx);
- }
- return context;
+ return ContextUtils.withValue(context, parentCtx);
}
}
diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt
index 7c8fa57714d..8b541b7c3f0 100644
--- a/compiler/src/test/golden/TestDeprecatedService.java.txt
+++ b/compiler/src/test/golden/TestDeprecatedService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.51.0-SNAPSHOT)",
+ value = "by gRPC proto compiler (version 1.52.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
@java.lang.Deprecated
diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
index d87bc631256..9ef5e4a0327 100644
--- a/compiler/src/test/golden/TestService.java.txt
+++ b/compiler/src/test/golden/TestService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.51.0-SNAPSHOT)",
+ value = "by gRPC proto compiler (version 1.52.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
public final class TestServiceGrpc {
diff --git a/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt
index dcd6f4e4bd5..2a9f951e913 100644
--- a/compiler/src/testLite/golden/TestDeprecatedService.java.txt
+++ b/compiler/src/testLite/golden/TestDeprecatedService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.51.0-SNAPSHOT)",
+ value = "by gRPC proto compiler (version 1.52.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
@java.lang.Deprecated
diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt
index fdf75a9bf9a..d5495156c4d 100644
--- a/compiler/src/testLite/golden/TestService.java.txt
+++ b/compiler/src/testLite/golden/TestService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.51.0-SNAPSHOT)",
+ value = "by gRPC proto compiler (version 1.52.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
public final class TestServiceGrpc {
diff --git a/context/src/test/java/io/grpc/testing/DeadlineSubject.java b/context/src/test/java/io/grpc/testing/DeadlineSubject.java
index 820f91248a1..5d4e86fac15 100644
--- a/context/src/test/java/io/grpc/testing/DeadlineSubject.java
+++ b/context/src/test/java/io/grpc/testing/DeadlineSubject.java
@@ -19,12 +19,12 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Fact.fact;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.truth.ComparableSubject;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
import io.grpc.Deadline;
-import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
@@ -32,6 +32,7 @@
/** Propositions for {@link Deadline} subjects. */
@SuppressWarnings("rawtypes") // Generics in this class are going away in a subsequent Truth.
public final class DeadlineSubject extends ComparableSubject {
+ public static final double NANOSECONDS_IN_A_SECOND = SECONDS.toNanos(1) * 1.0;
private static final Subject.Factory deadlineFactory =
new Factory();
@@ -60,14 +61,14 @@ public void of(Deadline expected) {
checkNotNull(actual, "actual value cannot be null. expected=%s", expected);
// This is probably overkill, but easier than thinking about overflow.
- BigInteger actualTimeRemaining = BigInteger.valueOf(actual.timeRemaining(NANOSECONDS));
- BigInteger expectedTimeRemaining = BigInteger.valueOf(expected.timeRemaining(NANOSECONDS));
- BigInteger deltaNanos = BigInteger.valueOf(timeUnit.toNanos(delta));
- if (actualTimeRemaining.subtract(expectedTimeRemaining).abs().compareTo(deltaNanos) > 0) {
+ long actualNanos = actual.timeRemaining(NANOSECONDS);
+ long expectedNanos = expected.timeRemaining(NANOSECONDS);
+ long deltaNanos = timeUnit.toNanos(delta) ;
+ if (Math.abs(actualNanos - expectedNanos) > deltaNanos) {
failWithoutActual(
- fact("expected", expected),
- fact("but was", actual),
- fact("outside tolerance in ns", deltaNanos));
+ fact("expected", expectedNanos / NANOSECONDS_IN_A_SECOND),
+ fact("but was", expectedNanos / NANOSECONDS_IN_A_SECOND),
+ fact("outside tolerance in seconds", deltaNanos / NANOSECONDS_IN_A_SECOND));
}
}
};
diff --git a/core/BUILD.bazel b/core/BUILD.bazel
index 60a08798d58..3ca51e66c94 100644
--- a/core/BUILD.bazel
+++ b/core/BUILD.bazel
@@ -65,13 +65,12 @@ java_library(
)
# Mirrors the dependencies included in the artifact on Maven Central for usage
-# with maven_install's override_targets. Purposefully does not export any
-# symbols, as it should only be used as a dep for pre-compiled binaries on
-# Maven Central.
+# with maven_install's override_targets. Should only be used as a dep for
+# pre-compiled binaries on Maven Central.
java_library(
name = "core_maven",
visibility = ["//visibility:public"],
- runtime_deps = [
+ exports = [
":inprocess",
":internal",
":util",
diff --git a/core/src/main/java/io/grpc/internal/ClientCallImpl.java b/core/src/main/java/io/grpc/internal/ClientCallImpl.java
index 31286c2bd7b..000ede77057 100644
--- a/core/src/main/java/io/grpc/internal/ClientCallImpl.java
+++ b/core/src/main/java/io/grpc/internal/ClientCallImpl.java
@@ -72,6 +72,7 @@ final class ClientCallImpl extends ClientCall {
private static final Logger log = Logger.getLogger(ClientCallImpl.class.getName());
private static final byte[] FULL_STREAM_DECOMPRESSION_ENCODINGS
= "gzip".getBytes(Charset.forName("US-ASCII"));
+ private static final double NANO_TO_SECS = 1.0 * TimeUnit.SECONDS.toNanos(1);
private final MethodDescriptor method;
private final Tag tag;
@@ -259,10 +260,12 @@ public void runInContext() {
} else {
ClientStreamTracer[] tracers =
GrpcUtil.getClientStreamTracers(callOptions, headers, 0, false);
- stream = new FailingClientStream(
- DEADLINE_EXCEEDED.withDescription(
- "ClientCall started after deadline exceeded: " + effectiveDeadline),
- tracers);
+ String deadlineName =
+ isFirstMin(callOptions.getDeadline(), context.getDeadline()) ? "CallOptions" : "Context";
+ String description = String.format(
+ "ClientCall started after %s deadline was exceeded .9%f seconds ago", deadlineName,
+ effectiveDeadline.timeRemaining(TimeUnit.NANOSECONDS) / NANO_TO_SECS);
+ stream = new FailingClientStream(DEADLINE_EXCEEDED.withDescription(description), tracers);
}
if (callExecutorIsDirect) {
@@ -431,6 +434,16 @@ private static Deadline min(@Nullable Deadline deadline0, @Nullable Deadline dea
return deadline0.minimum(deadline1);
}
+ private static boolean isFirstMin(@Nullable Deadline deadline0, @Nullable Deadline deadline1) {
+ if (deadline0 == null) {
+ return false;
+ }
+ if (deadline1 == null) {
+ return true;
+ }
+ return deadline0.isBefore(deadline1);
+ }
+
@Override
public void request(int numMessages) {
PerfMark.startTask("ClientCall.request", tag);
diff --git a/core/src/main/java/io/grpc/internal/DelayedClientCall.java b/core/src/main/java/io/grpc/internal/DelayedClientCall.java
index 42cedddd0e7..ee600e52d68 100644
--- a/core/src/main/java/io/grpc/internal/DelayedClientCall.java
+++ b/core/src/main/java/io/grpc/internal/DelayedClientCall.java
@@ -81,6 +81,17 @@ protected DelayedClientCall(
initialDeadlineMonitor = scheduleDeadlineIfNeeded(scheduler, deadline);
}
+ // If one argument is null, consider the other the "Before"
+ private boolean isAbeforeB(@Nullable Deadline a, @Nullable Deadline b) {
+ if (b == null) {
+ return true;
+ } else if (a == null) {
+ return false;
+ }
+
+ return a.isBefore(b);
+ }
+
@Nullable
private ScheduledFuture> scheduleDeadlineIfNeeded(
ScheduledExecutorService scheduler, @Nullable Deadline deadline) {
@@ -90,8 +101,9 @@ private ScheduledFuture> scheduleDeadlineIfNeeded(
}
long remainingNanos = Long.MAX_VALUE;
if (deadline != null) {
- remainingNanos = Math.min(remainingNanos, deadline.timeRemaining(NANOSECONDS));
+ remainingNanos = deadline.timeRemaining(NANOSECONDS);
}
+
if (contextDeadline != null && contextDeadline.timeRemaining(NANOSECONDS) < remainingNanos) {
remainingNanos = contextDeadline.timeRemaining(NANOSECONDS);
if (logger.isLoggable(Level.FINE)) {
@@ -110,13 +122,19 @@ private ScheduledFuture> scheduleDeadlineIfNeeded(
logger.fine(builder.toString());
}
}
+
long seconds = Math.abs(remainingNanos) / TimeUnit.SECONDS.toNanos(1);
long nanos = Math.abs(remainingNanos) % TimeUnit.SECONDS.toNanos(1);
final StringBuilder buf = new StringBuilder();
+ String deadlineName = isAbeforeB(contextDeadline, deadline) ? "Context" : "CallOptions";
if (remainingNanos < 0) {
- buf.append("ClientCall started after deadline exceeded. Deadline exceeded after -");
+ buf.append("ClientCall started after ");
+ buf.append(deadlineName);
+ buf.append(" deadline was exceeded. Deadline has been exceeded for ");
} else {
- buf.append("Deadline exceeded after ");
+ buf.append("Deadline ");
+ buf.append(deadlineName);
+ buf.append(" will be exceeded in ");
}
buf.append(seconds);
buf.append(String.format(Locale.US, ".%09d", nanos));
diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java
index 0159a0b5275..3d3677eb134 100644
--- a/core/src/main/java/io/grpc/internal/GrpcUtil.java
+++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java
@@ -217,7 +217,7 @@ public byte[] parseAsciiString(byte[] serialized) {
public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults();
- private static final String IMPLEMENTATION_VERSION = "1.51.0-SNAPSHOT"; // CURRENT_GRPC_VERSION
+ private static final String IMPLEMENTATION_VERSION = "1.52.0"; // CURRENT_GRPC_VERSION
/**
* The default timeout in nanos for a keepalive ping request.
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index 9cc7d70d1e7..0311a6d2e34 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -1942,13 +1942,14 @@ private final class SubchannelImpl extends AbstractSubchannel {
ScheduledHandle delayedShutdownTask;
SubchannelImpl(CreateSubchannelArgs args, LbHelperImpl helper) {
+ checkNotNull(args, "args");
addressGroups = args.getAddresses();
if (authorityOverride != null) {
List eagsWithoutOverrideAttr =
stripOverrideAuthorityAttributes(args.getAddresses());
args = args.toBuilder().setAddresses(eagsWithoutOverrideAttr).build();
}
- this.args = checkNotNull(args, "args");
+ this.args = args;
this.helper = checkNotNull(helper, "helper");
subchannelLogId = InternalLogId.allocate("Subchannel", /*details=*/ authority());
subchannelTracer = new ChannelTracer(
diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java
index cb94195cce1..46da45aebd4 100644
--- a/core/src/main/java/io/grpc/internal/RetriableStream.java
+++ b/core/src/main/java/io/grpc/internal/RetriableStream.java
@@ -107,6 +107,8 @@ public void uncaughtException(Thread t, Throwable e) {
*/
private final AtomicBoolean noMoreTransparentRetry = new AtomicBoolean();
private final AtomicInteger localOnlyTransparentRetries = new AtomicInteger();
+ private final AtomicInteger inFlightSubStreams = new AtomicInteger();
+ private Status savedCancellationReason;
// Used for recording the share of buffer used for the current call out of the channel buffer.
// This field would not be necessary if there is no channel buffer limit.
@@ -220,7 +222,16 @@ private void commitAndRun(Substream winningSubstream) {
}
}
+ @Nullable // returns null when cancelled
private Substream createSubstream(int previousAttemptCount, boolean isTransparentRetry) {
+ // increment only when >= 0, i.e. not cancelled
+ int inFlight;
+ do {
+ inFlight = inFlightSubStreams.get();
+ if (inFlight < 0) {
+ return null;
+ }
+ } while (!inFlightSubStreams.compareAndSet(inFlight, inFlight + 1));
Substream sub = new Substream(previousAttemptCount);
// one tracer per substream
final ClientStreamTracer bufferSizeTracer = new BufferSizeTracer(sub);
@@ -367,6 +378,9 @@ public final void start(ClientStreamListener listener) {
}
Substream substream = createSubstream(0, false);
+ if (substream == null) {
+ return;
+ }
if (isHedging) {
FutureCanceller scheduledHedgingRef = null;
@@ -434,16 +448,19 @@ private final class HedgingRunnable implements Runnable {
@Override
public void run() {
+ // It's safe to read state.hedgingAttemptCount here.
+ // If this run is not cancelled, the value of state.hedgingAttemptCount won't change
+ // until state.addActiveHedge() is called subsequently, even the state could possibly
+ // change.
+ Substream newSubstream = createSubstream(state.hedgingAttemptCount, false);
+ if (newSubstream == null) {
+ return;
+ }
callExecutor.execute(
new Runnable() {
@SuppressWarnings("GuardedBy")
@Override
public void run() {
- // It's safe to read state.hedgingAttemptCount here.
- // If this run is not cancelled, the value of state.hedgingAttemptCount won't change
- // until state.addActiveHedge() is called subsequently, even the state could possibly
- // change.
- Substream newSubstream = createSubstream(state.hedgingAttemptCount, false);
boolean cancelled = false;
FutureCanceller future = null;
@@ -489,16 +506,11 @@ public final void cancel(final Status reason) {
Runnable runnable = commit(noopSubstream);
if (runnable != null) {
+ savedCancellationReason = reason;
runnable.run();
- listenerSerializeExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- isClosed = true;
- masterListener.closed(reason, RpcProgress.PROCESSED, new Metadata());
-
- }
- });
+ if (inFlightSubStreams.addAndGet(Integer.MIN_VALUE) == Integer.MIN_VALUE) {
+ safeCloseMasterListener(reason, RpcProgress.PROCESSED, new Metadata());
+ }
return;
}
@@ -803,6 +815,17 @@ private void freezeHedging() {
}
}
+ private void safeCloseMasterListener(Status status, RpcProgress progress, Metadata metadata) {
+ listenerSerializeExecutor.execute(
+ new Runnable() {
+ @Override
+ public void run() {
+ isClosed = true;
+ masterListener.closed(status, progress, metadata);
+ }
+ });
+ }
+
private interface BufferEntry {
/** Replays the buffer entry with the given stream. */
void runWith(Substream substream);
@@ -840,19 +863,18 @@ public void closed(
closedSubstreamsInsight.append(status.getCode());
}
+ if (inFlightSubStreams.decrementAndGet() == Integer.MIN_VALUE) {
+ assert savedCancellationReason != null;
+ safeCloseMasterListener(savedCancellationReason, RpcProgress.PROCESSED, new Metadata());
+ return;
+ }
+
// handle a race between buffer limit exceeded and closed, when setting
// substream.bufferLimitExceeded = true happens before state.substreamClosed(substream).
if (substream.bufferLimitExceeded) {
commitAndRun(substream);
if (state.winningSubstream == substream) {
- listenerSerializeExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- isClosed = true;
- masterListener.closed(status, rpcProgress, trailers);
- }
- });
+ safeCloseMasterListener(status, rpcProgress, trailers);
}
return;
}
@@ -863,14 +885,7 @@ public void run() {
Status tooManyTransparentRetries = Status.INTERNAL
.withDescription("Too many transparent retries. Might be a bug in gRPC")
.withCause(status.asRuntimeException());
- listenerSerializeExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- isClosed = true;
- masterListener.closed(tooManyTransparentRetries, rpcProgress, trailers);
- }
- });
+ safeCloseMasterListener(tooManyTransparentRetries, rpcProgress, trailers);
}
return;
}
@@ -881,6 +896,9 @@ public void run() {
&& noMoreTransparentRetry.compareAndSet(false, true))) {
// transparent retry
final Substream newSubstream = createSubstream(substream.previousAttemptCount, true);
+ if (newSubstream == null) {
+ return;
+ }
if (isHedging) {
boolean commit = false;
synchronized (lock) {
@@ -942,6 +960,11 @@ public void run() {
} else {
RetryPlan retryPlan = makeRetryDecision(status, trailers);
if (retryPlan.shouldRetry) {
+ // retry
+ Substream newSubstream = createSubstream(substream.previousAttemptCount + 1, false);
+ if (newSubstream == null) {
+ return;
+ }
// The check state.winningSubstream == null, checking if is not already committed, is
// racy, but is still safe b/c the retry will also handle committed/cancellation
FutureCanceller scheduledRetryCopy;
@@ -955,10 +978,6 @@ public void run() {
new Runnable() {
@Override
public void run() {
- // retry
- Substream newSubstream = createSubstream(
- substream.previousAttemptCount + 1,
- false);
drain(newSubstream);
}
});
@@ -978,14 +997,7 @@ public void run() {
commitAndRun(substream);
if (state.winningSubstream == substream) {
- listenerSerializeExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- isClosed = true;
- masterListener.closed(status, rpcProgress, trailers);
- }
- });
+ safeCloseMasterListener(status, rpcProgress, trailers);
}
}
diff --git a/core/src/test/java/io/grpc/internal/ClientCallImplTest.java b/core/src/test/java/io/grpc/internal/ClientCallImplTest.java
index e409f2f9df4..687a89abdd8 100644
--- a/core/src/test/java/io/grpc/internal/ClientCallImplTest.java
+++ b/core/src/test/java/io/grpc/internal/ClientCallImplTest.java
@@ -786,7 +786,7 @@ public void deadlineExceededBeforeCallStarted() {
verify(callListener, timeout(1000)).onClose(statusCaptor.capture(), any(Metadata.class));
assertEquals(Status.Code.DEADLINE_EXCEEDED, statusCaptor.getValue().getCode());
assertThat(statusCaptor.getValue().getDescription())
- .startsWith("ClientCall started after deadline exceeded");
+ .startsWith("ClientCall started after CallOptions deadline was exceeded");
verifyNoInteractions(clientStreamProvider);
}
diff --git a/core/src/test/java/io/grpc/internal/RetriableStreamTest.java b/core/src/test/java/io/grpc/internal/RetriableStreamTest.java
index f20e772e92b..12bf697027c 100644
--- a/core/src/test/java/io/grpc/internal/RetriableStreamTest.java
+++ b/core/src/test/java/io/grpc/internal/RetriableStreamTest.java
@@ -283,6 +283,7 @@ public Void answer(InvocationOnMock in) {
doReturn(mockStream2).when(retriableStreamRecorder).newSubstream(1);
sublistenerCaptor1.getValue().closed(
Status.fromCode(RETRIABLE_STATUS_CODE_2), PROCESSED, new Metadata());
+ inOrder.verify(retriableStreamRecorder).newSubstream(1);
assertEquals(1, fakeClock.numPendingTasks());
// send more messages during backoff
@@ -294,7 +295,6 @@ public Void answer(InvocationOnMock in) {
assertEquals(1, fakeClock.numPendingTasks());
fakeClock.forwardTime(1L, TimeUnit.SECONDS);
assertEquals(0, fakeClock.numPendingTasks());
- inOrder.verify(retriableStreamRecorder).newSubstream(1);
inOrder.verify(mockStream2).setAuthority(AUTHORITY);
inOrder.verify(mockStream2).setCompressor(COMPRESSOR);
inOrder.verify(mockStream2).setDecompressorRegistry(DECOMPRESSOR_REGISTRY);
@@ -339,6 +339,7 @@ public Void answer(InvocationOnMock in) {
doReturn(mockStream3).when(retriableStreamRecorder).newSubstream(2);
sublistenerCaptor2.getValue().closed(
Status.fromCode(RETRIABLE_STATUS_CODE_1), PROCESSED, new Metadata());
+ inOrder.verify(retriableStreamRecorder).newSubstream(2);
assertEquals(1, fakeClock.numPendingTasks());
// send more messages during backoff
@@ -353,7 +354,6 @@ public Void answer(InvocationOnMock in) {
assertEquals(1, fakeClock.numPendingTasks());
fakeClock.forwardTime(1L, TimeUnit.SECONDS);
assertEquals(0, fakeClock.numPendingTasks());
- inOrder.verify(retriableStreamRecorder).newSubstream(2);
inOrder.verify(mockStream3).setAuthority(AUTHORITY);
inOrder.verify(mockStream3).setCompressor(COMPRESSOR);
inOrder.verify(mockStream3).setDecompressorRegistry(DECOMPRESSOR_REGISTRY);
@@ -792,6 +792,8 @@ public boolean isReady() {
public void cancelWhileDraining() {
ArgumentCaptor sublistenerCaptor1 =
ArgumentCaptor.forClass(ClientStreamListener.class);
+ ArgumentCaptor sublistenerCaptor2 =
+ ArgumentCaptor.forClass(ClientStreamListener.class);
ClientStream mockStream1 = mock(ClientStream.class);
ClientStream mockStream2 =
mock(
@@ -818,7 +820,7 @@ public void request(int numMessages) {
Status.fromCode(RETRIABLE_STATUS_CODE_1), PROCESSED, new Metadata());
fakeClock.forwardTime((long) (INITIAL_BACKOFF_IN_SECONDS * FAKE_RANDOM), TimeUnit.SECONDS);
- inOrder.verify(mockStream2).start(any(ClientStreamListener.class));
+ inOrder.verify(mockStream2).start(sublistenerCaptor2.capture());
inOrder.verify(mockStream2).request(3);
inOrder.verify(retriableStreamRecorder).postCommit();
ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Status.class);
@@ -826,6 +828,7 @@ public void request(int numMessages) {
assertThat(statusCaptor.getValue().getCode()).isEqualTo(Code.CANCELLED);
assertThat(statusCaptor.getValue().getDescription())
.isEqualTo("Stream thrown away because RetriableStream committed");
+ sublistenerCaptor2.getValue().closed(Status.CANCELLED, PROCESSED, new Metadata());
verify(masterListener).closed(
statusCaptor.capture(), any(RpcProgress.class), any(Metadata.class));
assertThat(statusCaptor.getValue().getCode()).isEqualTo(Code.CANCELLED);
@@ -848,6 +851,8 @@ public void start(ClientStreamListener listener) {
Status.CANCELLED.withDescription("cancelled while retry start"));
}
}));
+ ArgumentCaptor sublistenerCaptor2 =
+ ArgumentCaptor.forClass(ClientStreamListener.class);
InOrder inOrder = inOrder(retriableStreamRecorder, mockStream1, mockStream2);
doReturn(mockStream1).when(retriableStreamRecorder).newSubstream(0);
@@ -860,13 +865,14 @@ public void start(ClientStreamListener listener) {
Status.fromCode(RETRIABLE_STATUS_CODE_1), PROCESSED, new Metadata());
fakeClock.forwardTime((long) (INITIAL_BACKOFF_IN_SECONDS * FAKE_RANDOM), TimeUnit.SECONDS);
- inOrder.verify(mockStream2).start(any(ClientStreamListener.class));
+ inOrder.verify(mockStream2).start(sublistenerCaptor2.capture());
inOrder.verify(retriableStreamRecorder).postCommit();
ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Status.class);
inOrder.verify(mockStream2).cancel(statusCaptor.capture());
assertThat(statusCaptor.getValue().getCode()).isEqualTo(Code.CANCELLED);
assertThat(statusCaptor.getValue().getDescription())
.isEqualTo("Stream thrown away because RetriableStream committed");
+ sublistenerCaptor2.getValue().closed(Status.CANCELLED, PROCESSED, new Metadata());
verify(masterListener).closed(
statusCaptor.capture(), any(RpcProgress.class), any(Metadata.class));
assertThat(statusCaptor.getValue().getCode()).isEqualTo(Code.CANCELLED);
@@ -1121,7 +1127,6 @@ public void perRpcBufferLimitExceededDuringBackoff() {
sublistenerCaptor1.getValue().closed(
Status.fromCode(RETRIABLE_STATUS_CODE_1), PROCESSED, new Metadata());
- // bufferSizeTracer.outboundWireSize() quits immediately while backoff b/c substream1 is closed
assertEquals(1, fakeClock.numPendingTasks());
bufferSizeTracer.outboundWireSize(2);
verify(retriableStreamRecorder, never()).postCommit();
@@ -1132,8 +1137,6 @@ public void perRpcBufferLimitExceededDuringBackoff() {
// bufferLimitExceeded
bufferSizeTracer.outboundWireSize(PER_RPC_BUFFER_LIMIT - 1);
- verify(retriableStreamRecorder, never()).postCommit();
- bufferSizeTracer.outboundWireSize(2);
verify(retriableStreamRecorder).postCommit();
verifyNoMoreInteractions(mockStream1);
@@ -2464,6 +2467,8 @@ public void hedging_cancelled() {
assertEquals(CANCELLED_BECAUSE_COMMITTED, statusCaptor.getValue().getDescription());
inOrder.verify(retriableStreamRecorder).postCommit();
+ sublistenerCaptor1.getValue().closed(Status.CANCELLED, PROCESSED, new Metadata());
+ sublistenerCaptor2.getValue().closed(Status.CANCELLED, PROCESSED, new Metadata());
inOrder.verify(masterListener).closed(
any(Status.class), any(RpcProgress.class), any(Metadata.class));
inOrder.verifyNoMoreInteractions();
diff --git a/cronet/README.md b/cronet/README.md
index e871a64ffbe..1b4be783faf 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.50.2'
+implementation 'io.grpc:grpc-cronet:1.52.0'
implementation 'com.google.android.gms:play-services-cronet:16.0.0'
```
diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md
index 46dd67504f2..24c1e3890d8 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.50.2'
-implementation 'io.grpc:grpc-okhttp:1.50.2'
+implementation 'io.grpc:grpc-android:1.52.0'
+implementation 'io.grpc:grpc-okhttp:1.52.0'
```
You also need permission to access the device's network state in your
diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel
index e7f00381ad1..2a5ed52b35c 100644
--- a/examples/BUILD.bazel
+++ b/examples/BUILD.bazel
@@ -135,3 +135,40 @@ java_binary(
":examples",
],
)
+
+java_binary(
+ name = "load-balance-client",
+ testonly = 1,
+ main_class = "io.grpc.examples.loadbalance.LoadBalanceClient",
+ runtime_deps = [
+ ":examples",
+ ],
+)
+
+java_binary(
+ name = "load-balance-server",
+ testonly = 1,
+ main_class = "io.grpc.examples.loadbalance.LoadBalanceServer",
+ runtime_deps = [
+ ":examples",
+ ],
+)
+
+java_binary(
+ name = "name-resolve-client",
+ testonly = 1,
+ main_class = "io.grpc.examples.nameresolve.NameResolveClient",
+ runtime_deps = [
+ ":examples",
+ ],
+)
+
+java_binary(
+ name = "name-resolve-server",
+ testonly = 1,
+ main_class = "io.grpc.examples.nameresolve.NameResolveServer",
+ runtime_deps = [
+ ":examples",
+ ],
+)
+
diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle
index 827609afe8d..502b34a8310 100644
--- a/examples/android/clientcache/app/build.gradle
+++ b/examples/android/clientcache/app/build.gradle
@@ -34,7 +34,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.21.7' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.52.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -54,12 +54,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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.52.0' // 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ testImplementation 'io.grpc:grpc-testing:1.52.0' // CURRENT_GRPC_VERSION
}
diff --git a/examples/android/clientcache/build.gradle b/examples/android/clientcache/build.gradle
index 8a94a30191e..d033a64046d 100644
--- a/examples/android/clientcache/build.gradle
+++ b/examples/android/clientcache/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
- classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18"
+ classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.19"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle
index 94e86df7f30..93adc585e6b 100644
--- a/examples/android/helloworld/app/build.gradle
+++ b/examples/android/helloworld/app/build.gradle
@@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.21.7' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.52.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -52,8 +52,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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.52.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/android/helloworld/build.gradle b/examples/android/helloworld/build.gradle
index 8a94a30191e..d033a64046d 100644
--- a/examples/android/helloworld/build.gradle
+++ b/examples/android/helloworld/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
- classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18"
+ classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.19"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle
index 953a14c2a73..91c8ad658c7 100644
--- a/examples/android/routeguide/app/build.gradle
+++ b/examples/android/routeguide/app/build.gradle
@@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.21.7' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.52.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -52,8 +52,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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.52.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/android/routeguide/build.gradle b/examples/android/routeguide/build.gradle
index b1083bb867a..7a37b9c0648 100644
--- a/examples/android/routeguide/build.gradle
+++ b/examples/android/routeguide/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
- classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18"
+ classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.19"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle
index fa70153bcb4..e77f7c8fdbe 100644
--- a/examples/android/strictmode/app/build.gradle
+++ b/examples/android/strictmode/app/build.gradle
@@ -33,7 +33,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.21.7' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.52.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -53,8 +53,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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.52.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.52.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/android/strictmode/build.gradle b/examples/android/strictmode/build.gradle
index 8a94a30191e..d033a64046d 100644
--- a/examples/android/strictmode/build.gradle
+++ b/examples/android/strictmode/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
- classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.18"
+ classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.19"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/examples/build.gradle b/examples/build.gradle
index 89e066d0680..4b80e67f607 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -2,7 +2,7 @@ plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.18'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}
@@ -22,7 +22,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.21.7'
def protocVersion = protobufVersion
@@ -140,6 +140,34 @@ task manualFlowControlServer(type: CreateStartScripts) {
classpath = startScripts.classpath
}
+task loadBalanceServer(type: CreateStartScripts) {
+ mainClass = 'io.grpc.examples.loadbalance.LoadBalanceServer'
+ applicationName = 'load-balance-server'
+ outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
+ classpath = startScripts.classpath
+}
+
+task loadBalanceClient(type: CreateStartScripts) {
+ mainClass = 'io.grpc.examples.loadbalance.LoadBalanceClient'
+ applicationName = 'load-balance-client'
+ outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
+ classpath = startScripts.classpath
+}
+
+task nameResolveServer(type: CreateStartScripts) {
+ mainClass = 'io.grpc.examples.nameresolve.NameResolveServer'
+ applicationName = 'name-resolve-server'
+ outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
+ classpath = startScripts.classpath
+}
+
+task nameResolveClient(type: CreateStartScripts) {
+ mainClass = 'io.grpc.examples.nameresolve.NameResolveClient'
+ applicationName = 'name-resolve-client'
+ outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
+ classpath = startScripts.classpath
+}
+
applicationDistribution.into('bin') {
from(routeGuideServer)
from(routeGuideClient)
@@ -152,5 +180,9 @@ applicationDistribution.into('bin') {
from(compressingHelloWorldClient)
from(manualFlowControlClient)
from(manualFlowControlServer)
+ from(loadBalanceServer)
+ from(loadBalanceClient)
+ from(nameResolveServer)
+ from(nameResolveClient)
fileMode = 0755
}
diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle
index eb8fa418068..0fc499d3d99 100644
--- a/examples/example-alts/build.gradle
+++ b/examples/example-alts/build.gradle
@@ -2,7 +2,7 @@ plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}
@@ -23,7 +23,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.21.7'
dependencies {
diff --git a/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsClient.java b/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsClient.java
index 96351808b25..991ad777309 100644
--- a/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsClient.java
+++ b/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsClient.java
@@ -16,7 +16,8 @@
package io.grpc.examples.alts;
-import io.grpc.alts.AltsChannelBuilder;
+import io.grpc.alts.AltsChannelCredentials;
+import io.grpc.Grpc;
import io.grpc.ManagedChannel;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -81,7 +82,8 @@ private void parseArgs(String[] args) {
private void run(String[] args) throws InterruptedException {
parseArgs(args);
ExecutorService executor = Executors.newFixedThreadPool(1);
- ManagedChannel channel = AltsChannelBuilder.forTarget(serverAddress).executor(executor).build();
+ ManagedChannel channel = Grpc.newChannelBuilder(serverAddress, AltsChannelCredentials.create())
+ .executor(executor).build();
try {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
HelloReply resp = stub.sayHello(HelloRequest.newBuilder().setName("Waldo").build());
diff --git a/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsServer.java b/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsServer.java
index fd662069cfd..6bc5226bf59 100644
--- a/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsServer.java
+++ b/examples/example-alts/src/main/java/io/grpc/examples/alts/HelloWorldAltsServer.java
@@ -16,7 +16,8 @@
package io.grpc.examples.alts;
-import io.grpc.alts.AltsServerBuilder;
+import io.grpc.alts.AltsServerCredentials;
+import io.grpc.Grpc;
import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc.GreeterImplBase;
import io.grpc.examples.helloworld.HelloReply;
@@ -82,7 +83,7 @@ private void parseArgs(String[] args) {
private void start(String[] args) throws IOException, InterruptedException {
parseArgs(args);
server =
- AltsServerBuilder.forPort(port)
+ Grpc.newServerBuilderForPort(port, AltsServerCredentials.create())
.addService(this)
.executor(Executors.newFixedThreadPool(1))
.build();
diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle
index 448ec374fdf..2da074f4f38 100644
--- a/examples/example-gauth/build.gradle
+++ b/examples/example-gauth/build.gradle
@@ -2,7 +2,7 @@ plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}
@@ -23,7 +23,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.21.7'
def protocVersion = protobufVersion
diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml
index 9f36e0e98b2..2cd72aa6ef7 100644
--- a/examples/example-gauth/pom.xml
+++ b/examples/example-gauth/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.51.0-SNAPSHOT
+ 1.52.0
example-gauth
https://github.com/grpc/grpc-java
UTF-8
- 1.51.0-SNAPSHOT
+ 1.52.0
3.21.7
1.7
diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle
index c3051b99264..f02b30af04e 100644
--- a/examples/example-hostname/build.gradle
+++ b/examples/example-hostname/build.gradle
@@ -2,7 +2,7 @@ plugins {
id 'application' // Provide convenience executables for trying out the examples.
id 'java'
- id "com.google.protobuf" version "0.8.17"
+ id "com.google.protobuf" version "0.8.19"
id 'com.google.cloud.tools.jib' version '3.1.4' // For releasing to Docker Hub
}
@@ -21,7 +21,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.21.7'
dependencies {
diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml
index e111c244f6f..b6384fad254 100644
--- a/examples/example-hostname/pom.xml
+++ b/examples/example-hostname/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.51.0-SNAPSHOT
+ 1.52.0
example-hostname
https://github.com/grpc/grpc-java
UTF-8
- 1.51.0-SNAPSHOT
+ 1.52.0
3.21.7
1.7
diff --git a/examples/example-hostname/src/main/java/io/grpc/examples/hostname/HostnameServer.java b/examples/example-hostname/src/main/java/io/grpc/examples/hostname/HostnameServer.java
index a6f2175914e..3c63296d7fa 100644
--- a/examples/example-hostname/src/main/java/io/grpc/examples/hostname/HostnameServer.java
+++ b/examples/example-hostname/src/main/java/io/grpc/examples/hostname/HostnameServer.java
@@ -16,6 +16,8 @@
package io.grpc.examples.hostname;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
@@ -49,7 +51,7 @@ public static void main(String[] args) throws IOException, InterruptedException
hostname = args[1];
}
HealthStatusManager health = new HealthStatusManager();
- final Server server = ServerBuilder.forPort(port)
+ final Server server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new HostnameGreeter(hostname))
.addService(ProtoReflectionService.newInstance())
.addService(health.getHealthService())
diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle
index 968ad9ca385..f2373fa4b65 100644
--- a/examples/example-jwt-auth/build.gradle
+++ b/examples/example-jwt-auth/build.gradle
@@ -2,7 +2,7 @@ plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}
@@ -22,7 +22,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.21.7'
def protocVersion = protobufVersion
diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml
index d6223b1e0d0..4b3abec4ec2 100644
--- a/examples/example-jwt-auth/pom.xml
+++ b/examples/example-jwt-auth/pom.xml
@@ -7,13 +7,13 @@
jar
- 1.51.0-SNAPSHOT
+ 1.52.0
example-jwt-auth
https://github.com/grpc/grpc-java
UTF-8
- 1.51.0-SNAPSHOT
+ 1.52.0
3.21.7
3.21.7
diff --git a/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthClient.java b/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthClient.java
index f6ea4c57e45..c5769625807 100644
--- a/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthClient.java
+++ b/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthClient.java
@@ -17,8 +17,9 @@
package io.grpc.examples.jwtauth;
import io.grpc.CallCredentials;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
@@ -42,12 +43,9 @@ public class AuthClient {
AuthClient(CallCredentials callCredentials, String host, int port) {
this(
callCredentials,
- ManagedChannelBuilder
- .forAddress(host, port)
- // Channels are secure by default (via SSL/TLS). For this example we disable TLS
- // to avoid needing certificates, but it is recommended to use a secure channel
- // while passing credentials.
- .usePlaintext()
+ // For this example we use plaintext to avoid needing certificates, but it is
+ // recommended to use TlsChannelCredentials.
+ Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create())
.build());
}
diff --git a/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthServer.java b/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthServer.java
index 90e7dff1458..208645e4fad 100644
--- a/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthServer.java
+++ b/examples/example-jwt-auth/src/main/java/io/grpc/examples/jwtauth/AuthServer.java
@@ -16,8 +16,9 @@
package io.grpc.examples.jwtauth;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
@@ -41,7 +42,7 @@ public AuthServer(int port) {
}
private void start() throws IOException {
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.intercept(new JwtServerInterceptor()) // add the JwtServerInterceptor
.build()
diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle
index ba2acf222bf..8b247c4b37f 100644
--- a/examples/example-orca/build.gradle
+++ b/examples/example-orca/build.gradle
@@ -1,7 +1,7 @@
plugins {
id 'application' // Provide convenience executables for trying out the examples.
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
id 'java'
@@ -17,7 +17,7 @@ repositories {
sourceCompatibility = 1.8
targetCompatibility = 1.8
-def grpcVersion = '1.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.21.7'
dependencies {
diff --git a/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsClient.java b/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsClient.java
index da231bd1f16..66143b44364 100644
--- a/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsClient.java
+++ b/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsClient.java
@@ -19,9 +19,10 @@
import static io.grpc.examples.orca.CustomBackendMetricsLoadBalancerProvider.EXAMPLE_LOAD_BALANCER;
import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.LoadBalancerRegistry;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -91,9 +92,8 @@ public static void main(String[] args) throws Exception {
LoadBalancerRegistry.getDefaultRegistry().register(
new CustomBackendMetricsLoadBalancerProvider());
- ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
.defaultLoadBalancingPolicy(EXAMPLE_LOAD_BALANCER)
- .usePlaintext()
.build();
try {
CustomBackendMetricsClient client = new CustomBackendMetricsClient(channel);
diff --git a/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsServer.java b/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsServer.java
index da76b3b5b2c..b04664da363 100644
--- a/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsServer.java
+++ b/examples/example-orca/src/main/java/io/grpc/examples/orca/CustomBackendMetricsServer.java
@@ -21,8 +21,9 @@
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.services.CallMetricRecorder;
import io.grpc.services.InternalCallMetricRecorder;
import io.grpc.services.MetricRecorder;
@@ -57,7 +58,7 @@ private void start() throws IOException {
// configuration to be as short as 1s, suitable for test demonstration.
BindableService orcaOobService =
OrcaServiceImpl.createService(executor, metricRecorder, 1, TimeUnit.SECONDS);
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
// Enable OOB custom backend metrics reporting.
.addService(orcaOobService)
diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle
index 66365ce2a70..76940b9a95d 100644
--- a/examples/example-tls/build.gradle
+++ b/examples/example-tls/build.gradle
@@ -2,7 +2,7 @@ plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}
@@ -23,7 +23,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.21.7'
dependencies {
diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml
index e3573aaa25d..de9d8b4ae3c 100644
--- a/examples/example-tls/pom.xml
+++ b/examples/example-tls/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.51.0-SNAPSHOT
+ 1.52.0
example-tls
https://github.com/grpc/grpc-java
UTF-8
- 1.51.0-SNAPSHOT
+ 1.52.0
3.21.7
2.0.54.Final
diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle
index 6acbaa35f59..14c8dd1e89e 100644
--- a/examples/example-xds/build.gradle
+++ b/examples/example-xds/build.gradle
@@ -1,7 +1,7 @@
plugins {
id 'application' // Provide convenience executables for trying out the examples.
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
- id 'com.google.protobuf' version '0.8.17'
+ id 'com.google.protobuf' version '0.8.19'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
id 'java'
@@ -22,7 +22,7 @@ targetCompatibility = 1.8
// 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.51.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.52.0' // CURRENT_GRPC_VERSION
def nettyTcNativeVersion = '2.0.31.Final'
def protocVersion = '3.21.7'
diff --git a/examples/pom.xml b/examples/pom.xml
index b6631152bd9..e90c527d7fa 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -6,18 +6,18 @@
jar
- 1.51.0-SNAPSHOT
+ 1.52.0
examples
https://github.com/grpc/grpc-java
UTF-8
- 1.51.0-SNAPSHOT
+ 1.52.0
3.21.7
3.21.7
-
- 1.7
- 1.7
+
+ 1.8
+ 1.8
diff --git a/examples/src/main/java/io/grpc/examples/advanced/HelloJsonClient.java b/examples/src/main/java/io/grpc/examples/advanced/HelloJsonClient.java
index 264fe76b7d3..9291e45bafe 100644
--- a/examples/src/main/java/io/grpc/examples/advanced/HelloJsonClient.java
+++ b/examples/src/main/java/io/grpc/examples/advanced/HelloJsonClient.java
@@ -20,8 +20,9 @@
import io.grpc.CallOptions;
import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.MethodDescriptor;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.GreeterGrpc;
@@ -49,8 +50,7 @@ public final class HelloJsonClient {
/** Construct client connecting to HelloWorld server at {@code host:port}. */
public HelloJsonClient(String host, int port) {
- channel = ManagedChannelBuilder.forAddress(host, port)
- .usePlaintext()
+ channel = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create())
.build();
blockingStub = new HelloJsonStub(channel);
}
diff --git a/examples/src/main/java/io/grpc/examples/advanced/HelloJsonServer.java b/examples/src/main/java/io/grpc/examples/advanced/HelloJsonServer.java
index 0a656dd52b8..0f4e5d28f16 100644
--- a/examples/src/main/java/io/grpc/examples/advanced/HelloJsonServer.java
+++ b/examples/src/main/java/io/grpc/examples/advanced/HelloJsonServer.java
@@ -19,8 +19,9 @@
import static io.grpc.stub.ServerCalls.asyncUnaryCall;
import io.grpc.BindableService;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.ServerServiceDefinition;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -50,7 +51,7 @@ public class HelloJsonServer {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.build()
.start();
diff --git a/examples/src/main/java/io/grpc/examples/errorhandling/DetailErrorSample.java b/examples/src/main/java/io/grpc/examples/errorhandling/DetailErrorSample.java
index b743b46b471..b026b6f32dc 100644
--- a/examples/src/main/java/io/grpc/examples/errorhandling/DetailErrorSample.java
+++ b/examples/src/main/java/io/grpc/examples/errorhandling/DetailErrorSample.java
@@ -27,11 +27,12 @@
import com.google.rpc.DebugInfo;
import io.grpc.CallOptions;
import io.grpc.ClientCall;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.InsecureServerCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.Metadata;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.Status;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.GreeterGrpc.GreeterBlockingStub;
@@ -73,7 +74,8 @@ public static void main(String[] args) throws Exception {
private ManagedChannel channel;
void run() throws Exception {
- Server server = ServerBuilder.forPort(0).addService(new GreeterGrpc.GreeterImplBase() {
+ Server server = Grpc.newServerBuilderForPort(0, InsecureServerCredentials.create())
+ .addService(new GreeterGrpc.GreeterImplBase() {
@Override
public void sayHello(HelloRequest request, StreamObserver responseObserver) {
Metadata trailers = new Metadata();
@@ -82,8 +84,8 @@ public void sayHello(HelloRequest request, StreamObserver responseOb
.asRuntimeException(trailers));
}
}).build().start();
- channel =
- ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext().build();
+ channel = Grpc.newChannelBuilderForAddress(
+ "localhost", server.getPort(), InsecureChannelCredentials.create()).build();
blockingCall();
futureCallDirect();
diff --git a/examples/src/main/java/io/grpc/examples/errorhandling/ErrorHandlingClient.java b/examples/src/main/java/io/grpc/examples/errorhandling/ErrorHandlingClient.java
index 4afd39b08fa..7e310433a90 100644
--- a/examples/src/main/java/io/grpc/examples/errorhandling/ErrorHandlingClient.java
+++ b/examples/src/main/java/io/grpc/examples/errorhandling/ErrorHandlingClient.java
@@ -25,11 +25,12 @@
import com.google.common.util.concurrent.Uninterruptibles;
import io.grpc.CallOptions;
import io.grpc.ClientCall;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.InsecureServerCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.Metadata;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.Status;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.GreeterGrpc.GreeterBlockingStub;
@@ -55,15 +56,16 @@ public static void main(String [] args) throws Exception {
void run() throws Exception {
// Port 0 means that the operating system will pick an available port to use.
- Server server = ServerBuilder.forPort(0).addService(new GreeterGrpc.GreeterImplBase() {
+ Server server = Grpc.newServerBuilderForPort(0, InsecureServerCredentials.create())
+ .addService(new GreeterGrpc.GreeterImplBase() {
@Override
public void sayHello(HelloRequest request, StreamObserver responseObserver) {
responseObserver.onError(Status.INTERNAL
.withDescription("Eggplant Xerxes Crybaby Overbite Narwhal").asRuntimeException());
}
}).build().start();
- channel =
- ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext().build();
+ channel = Grpc.newChannelBuilderForAddress(
+ "localhost", server.getPort(), InsecureChannelCredentials.create()).build();
blockingCall();
futureCallDirect();
diff --git a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldClient.java b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldClient.java
index 410b0c7c14c..49e9cb36d53 100644
--- a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldClient.java
+++ b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldClient.java
@@ -16,8 +16,9 @@
package io.grpc.examples.experimental;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -42,8 +43,7 @@ public class CompressingHelloWorldClient {
/** Construct client connecting to HelloWorld server at {@code host:port}. */
public CompressingHelloWorldClient(String host, int port) {
- channel = ManagedChannelBuilder.forAddress(host, port)
- .usePlaintext()
+ channel = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create())
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
diff --git a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerAllMethods.java b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerAllMethods.java
index 23c51a6d26c..794d7196f35 100644
--- a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerAllMethods.java
+++ b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerAllMethods.java
@@ -20,9 +20,10 @@
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Metadata;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
@@ -44,7 +45,7 @@ public class CompressingHelloWorldServerAllMethods {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
/* This method call adds the Interceptor to enable compressed server responses for all RPCs */
.intercept(new ServerInterceptor() {
@Override
diff --git a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerPerMethod.java b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerPerMethod.java
index 0ccf38184d3..b7faa96d7b4 100644
--- a/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerPerMethod.java
+++ b/examples/src/main/java/io/grpc/examples/experimental/CompressingHelloWorldServerPerMethod.java
@@ -20,8 +20,9 @@
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
@@ -40,7 +41,7 @@ public class CompressingHelloWorldServerPerMethod {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.build()
.start();
diff --git a/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java b/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
index 93d106dba9e..52287040ba0 100644
--- a/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
+++ b/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
@@ -19,8 +19,9 @@
import io.grpc.Channel;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -43,8 +44,8 @@ public class CustomHeaderClient {
* A custom client.
*/
private CustomHeaderClient(String host, int port) {
- originChannel = ManagedChannelBuilder.forAddress(host, port)
- .usePlaintext()
+ originChannel = Grpc
+ .newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create())
.build();
ClientInterceptor interceptor = new HeaderClientInterceptor();
Channel channel = ClientInterceptors.intercept(originChannel, interceptor);
diff --git a/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java b/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
index ae80045603c..75a3d24934f 100644
--- a/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
+++ b/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
@@ -16,8 +16,9 @@
package io.grpc.examples.header;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.ServerInterceptors;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -39,7 +40,7 @@ public class CustomHeaderServer {
private Server server;
private void start() throws IOException {
- server = ServerBuilder.forPort(PORT)
+ server = Grpc.newServerBuilderForPort(PORT, InsecureServerCredentials.create())
.addService(ServerInterceptors.intercept(new GreeterImpl(), new HeaderServerInterceptor()))
.build()
.start();
diff --git a/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldClient.java b/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldClient.java
index 30f7beb49a0..429cceb50c3 100644
--- a/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldClient.java
+++ b/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldClient.java
@@ -20,6 +20,8 @@
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
@@ -51,11 +53,8 @@ public class HedgingHelloWorldClient {
/** Construct client connecting to HelloWorld server at {@code host:port}. */
public HedgingHelloWorldClient(String host, int port, boolean hedging) {
-
- ManagedChannelBuilder> channelBuilder = ManagedChannelBuilder.forAddress(host, port)
- // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
- // needing certificates.
- .usePlaintext();
+ ManagedChannelBuilder> channelBuilder
+ = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create());
if (hedging) {
Map hedgingServiceConfig =
new Gson()
diff --git a/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldServer.java b/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldServer.java
index b934e8514ac..784269eea1c 100644
--- a/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldServer.java
+++ b/examples/src/main/java/io/grpc/examples/hedging/HedgingHelloWorldServer.java
@@ -16,9 +16,10 @@
package io.grpc.examples.hedging;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Metadata;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
@@ -43,7 +44,7 @@ public class HedgingHelloWorldServer {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.intercept(new LatencyInjectionInterceptor())
.build()
diff --git a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
index d00bca1e216..6b186facf46 100644
--- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
+++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
@@ -17,8 +17,9 @@
package io.grpc.examples.helloworld;
import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@@ -81,10 +82,10 @@ public static void main(String[] args) throws Exception {
// Create a communication channel to the server, known as a Channel. Channels are thread-safe
// and reusable. It is common to create channels at the beginning of your application and reuse
// them until the application shuts down.
- ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
- // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
- // needing certificates.
- .usePlaintext()
+ //
+ // For the example we use plaintext insecure credentials to avoid needing TLS certificates. To
+ // use TLS, use TlsChannelCredentials instead.
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
.build();
try {
HelloWorldClient client = new HelloWorldClient(channel);
diff --git a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
index 12836a4c828..81027587031 100644
--- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
+++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
@@ -16,8 +16,9 @@
package io.grpc.examples.helloworld;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@@ -34,7 +35,7 @@ public class HelloWorldServer {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.build()
.start();
diff --git a/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolver.java b/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolver.java
new file mode 100644
index 00000000000..f562f0ac107
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolver.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2022 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.examples.loadbalance;
+
+import com.google.common.collect.ImmutableMap;
+import io.grpc.EquivalentAddressGroup;
+import io.grpc.NameResolver;
+import io.grpc.Status;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static io.grpc.examples.loadbalance.LoadBalanceClient.exampleServiceName;
+
+public class ExampleNameResolver extends NameResolver {
+
+ private Listener2 listener;
+
+ private final URI uri;
+
+ private final Map> addrStore;
+
+ public ExampleNameResolver(URI targetUri) {
+ this.uri = targetUri;
+ // This is a fake name resolver, so we just hard code the address here.
+ addrStore = ImmutableMap.>builder()
+ .put(exampleServiceName,
+ Stream.iterate(LoadBalanceServer.startPort,p->p+1)
+ .limit(LoadBalanceServer.serverCount)
+ .map(port->new InetSocketAddress("localhost",port))
+ .collect(Collectors.toList())
+ )
+ .build();
+ }
+
+ @Override
+ public String getServiceAuthority() {
+ // Be consistent with behavior in grpc-go, authority is saved in Host field of URI.
+ if (uri.getHost() != null) {
+ return uri.getHost();
+ }
+ return "no host";
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public void start(Listener2 listener) {
+ this.listener = listener;
+ this.resolve();
+ }
+
+ @Override
+ public void refresh() {
+ this.resolve();
+ }
+
+ private void resolve() {
+ List addresses = addrStore.get(uri.getPath().substring(1));
+ try {
+ List equivalentAddressGroup = addresses.stream()
+ // convert to socket address
+ .map(this::toSocketAddress)
+ // every socket address is a single EquivalentAddressGroup, so they can be accessed randomly
+ .map(Arrays::asList)
+ .map(this::addrToEquivalentAddressGroup)
+ .collect(Collectors.toList());
+
+ ResolutionResult resolutionResult = ResolutionResult.newBuilder()
+ .setAddresses(equivalentAddressGroup)
+ .build();
+
+ this.listener.onResult(resolutionResult);
+
+ } catch (Exception e){
+ // when error occurs, notify listener
+ this.listener.onError(Status.UNAVAILABLE.withDescription("Unable to resolve host ").withCause(e));
+ }
+ }
+
+ private SocketAddress toSocketAddress(InetSocketAddress address) {
+ return new InetSocketAddress(address.getHostName(), address.getPort());
+ }
+
+ private EquivalentAddressGroup addrToEquivalentAddressGroup(List addrList) {
+ return new EquivalentAddressGroup(addrList);
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolverProvider.java b/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolverProvider.java
new file mode 100644
index 00000000000..ee966fd044c
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/loadbalance/ExampleNameResolverProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 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.examples.loadbalance;
+
+import io.grpc.NameResolver;
+import io.grpc.NameResolverProvider;
+
+import java.net.URI;
+
+import static io.grpc.examples.loadbalance.LoadBalanceClient.exampleScheme;
+
+public class ExampleNameResolverProvider extends NameResolverProvider {
+ @Override
+ public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
+ return new ExampleNameResolver(targetUri);
+ }
+
+ @Override
+ protected boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ protected int priority() {
+ return 5;
+ }
+
+ @Override
+ // gRPC choose the first NameResolverProvider that supports the target URI scheme.
+ public String getDefaultScheme() {
+ return exampleScheme;
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceClient.java b/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceClient.java
new file mode 100644
index 00000000000..97444922871
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceClient.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2022 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.examples.loadbalance;
+
+import io.grpc.*;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LoadBalanceClient {
+ private static final Logger logger = Logger.getLogger(LoadBalanceClient.class.getName());
+
+ public static final String exampleScheme = "example";
+ public static final String exampleServiceName = "lb.example.grpc.io";
+
+ private final GreeterGrpc.GreeterBlockingStub blockingStub;
+
+ public LoadBalanceClient(Channel channel) {
+ blockingStub = GreeterGrpc.newBlockingStub(channel);
+ }
+
+ public void greet(String name) {
+ HelloRequest request = HelloRequest.newBuilder().setName(name).build();
+ HelloReply response;
+ try {
+ response = blockingStub.sayHello(request);
+ } catch (StatusRuntimeException e) {
+ logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
+ return;
+ }
+ logger.info("Greeting: " + response.getMessage());
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ NameResolverRegistry.getDefaultRegistry().register(new ExampleNameResolverProvider());
+
+ String target = String.format("%s:///%s", exampleScheme, exampleServiceName);
+
+ logger.info("Use default first_pick load balance policy");
+ ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
+ .usePlaintext()
+ .build();
+ try {
+ LoadBalanceClient client = new LoadBalanceClient(channel);
+ for (int i = 0; i < 5; i++) {
+ client.greet("request" + i);
+ }
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+
+ logger.info("Change to round_robin policy");
+ channel = ManagedChannelBuilder.forTarget(target)
+ .defaultLoadBalancingPolicy("round_robin")
+ .usePlaintext()
+ .build();
+ try {
+ LoadBalanceClient client = new LoadBalanceClient(channel);
+ for (int i = 0; i < 5; i++) {
+ client.greet("request" + i);
+ }
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceServer.java b/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceServer.java
new file mode 100644
index 00000000000..c97d209497a
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/loadbalance/LoadBalanceServer.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2022 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.examples.loadbalance;
+
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.stub.StreamObserver;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+public class LoadBalanceServer {
+ private static final Logger logger = Logger.getLogger(LoadBalanceServer.class.getName());
+ static public final int serverCount = 3;
+ static public final int startPort = 50051;
+ private Server[] servers;
+
+ private void start() throws IOException {
+ servers = new Server[serverCount];
+ for (int i = 0; i < serverCount; i++) {
+ int port = startPort + i;
+ servers[i] = ServerBuilder.forPort(port)
+ .addService(new GreeterImpl(port))
+ .build()
+ .start();
+ logger.info("Server started, listening on " + port);
+ }
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ try {
+ LoadBalanceServer.this.stop();
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ System.err.println("*** server shut down");
+ }));
+ }
+
+ private void stop() throws InterruptedException {
+ for (int i = 0; i < serverCount; i++) {
+ if (servers[i] != null) {
+ servers[i].shutdown().awaitTermination(30, TimeUnit.SECONDS);
+ }
+ }
+ }
+
+ private void blockUntilShutdown() throws InterruptedException {
+ for (int i = 0; i < serverCount; i++) {
+ if (servers[i] != null) {
+ servers[i].awaitTermination();
+ }
+ }
+ }
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ final LoadBalanceServer server = new LoadBalanceServer();
+ server.start();
+ server.blockUntilShutdown();
+ }
+
+ static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
+
+ int port;
+
+ public GreeterImpl(int port) {
+ this.port = port;
+ }
+
+ @Override
+ public void sayHello(HelloRequest req, StreamObserver responseObserver) {
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName() + " from server<" + this.port + ">").build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolver.java b/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolver.java
new file mode 100644
index 00000000000..95bf20dd580
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolver.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2022 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.examples.nameresolve;
+
+import com.google.common.collect.ImmutableMap;
+import io.grpc.EquivalentAddressGroup;
+import io.grpc.NameResolver;
+import io.grpc.Status;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static io.grpc.examples.loadbalance.LoadBalanceClient.exampleServiceName;
+
+public class ExampleNameResolver extends NameResolver {
+
+ private final URI uri;
+ private final Map> addrStore;
+ private Listener2 listener;
+
+ public ExampleNameResolver(URI targetUri) {
+ this.uri = targetUri;
+ // This is a fake name resolver, so we just hard code the address here.
+ addrStore = ImmutableMap.>builder()
+ .put(exampleServiceName,
+ Stream.iterate(NameResolveServer.startPort, p -> p + 1)
+ .limit(NameResolveServer.serverCount)
+ .map(port -> new InetSocketAddress("localhost", port))
+ .collect(Collectors.toList())
+ )
+ .build();
+ }
+
+ @Override
+ public String getServiceAuthority() {
+ // Be consistent with behavior in grpc-go, authority is saved in Host field of URI.
+ if (uri.getHost() != null) {
+ return uri.getHost();
+ }
+ return "no host";
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public void start(Listener2 listener) {
+ this.listener = listener;
+ this.resolve();
+ }
+
+ @Override
+ public void refresh() {
+ this.resolve();
+ }
+
+ private void resolve() {
+ List addresses = addrStore.get(uri.getPath().substring(1));
+ try {
+ List equivalentAddressGroup = addresses.stream()
+ // convert to socket address
+ .map(this::toSocketAddress)
+ // every socket address is a single EquivalentAddressGroup, so they can be accessed randomly
+ .map(Arrays::asList)
+ .map(this::addrToEquivalentAddressGroup)
+ .collect(Collectors.toList());
+
+ ResolutionResult resolutionResult = ResolutionResult.newBuilder()
+ .setAddresses(equivalentAddressGroup)
+ .build();
+
+ this.listener.onResult(resolutionResult);
+
+ } catch (Exception e) {
+ // when error occurs, notify listener
+ this.listener.onError(Status.UNAVAILABLE.withDescription("Unable to resolve host ").withCause(e));
+ }
+ }
+
+ private SocketAddress toSocketAddress(InetSocketAddress address) {
+ return new InetSocketAddress(address.getHostName(), address.getPort());
+ }
+
+ private EquivalentAddressGroup addrToEquivalentAddressGroup(List addrList) {
+ return new EquivalentAddressGroup(addrList);
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolverProvider.java b/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolverProvider.java
new file mode 100644
index 00000000000..cd05f3214f6
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolverProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 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.examples.nameresolve;
+
+import io.grpc.NameResolver;
+import io.grpc.NameResolverProvider;
+
+import java.net.URI;
+
+import static io.grpc.examples.loadbalance.LoadBalanceClient.exampleScheme;
+
+public class ExampleNameResolverProvider extends NameResolverProvider {
+ @Override
+ public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
+ return new ExampleNameResolver(targetUri);
+ }
+
+ @Override
+ protected boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ protected int priority() {
+ return 5;
+ }
+
+ @Override
+ // gRPC choose the first NameResolverProvider that supports the target URI scheme.
+ public String getDefaultScheme() {
+ return exampleScheme;
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveClient.java b/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveClient.java
new file mode 100644
index 00000000000..ac6fdd32549
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveClient.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2022 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.examples.nameresolve;
+
+import io.grpc.*;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class NameResolveClient {
+ public static final String exampleScheme = "example";
+ public static final String exampleServiceName = "lb.example.grpc.io";
+ private static final Logger logger = Logger.getLogger(NameResolveClient.class.getName());
+ private final GreeterGrpc.GreeterBlockingStub blockingStub;
+
+ public NameResolveClient(Channel channel) {
+ blockingStub = GreeterGrpc.newBlockingStub(channel);
+ }
+
+ public static void main(String[] args) throws Exception {
+ NameResolverRegistry.getDefaultRegistry().register(new ExampleNameResolverProvider());
+
+ logger.info("Use default DNS resolver");
+ ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:50051")
+ .usePlaintext()
+ .build();
+ try {
+ NameResolveClient client = new NameResolveClient(channel);
+ for (int i = 0; i < 5; i++) {
+ client.greet("request" + i);
+ }
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+
+ logger.info("Change to use example name resolver");
+ /*
+ Dial to "example:///resolver.example.grpc.io", use {@link ExampleNameResolver} to create connection
+ "resolver.example.grpc.io" is converted to {@link java.net.URI.path}
+ */
+ channel = ManagedChannelBuilder.forTarget(
+ String.format("%s:///%s", exampleScheme, exampleServiceName))
+ .defaultLoadBalancingPolicy("round_robin")
+ .usePlaintext()
+ .build();
+ try {
+ NameResolveClient client = new NameResolveClient(channel);
+ for (int i = 0; i < 5; i++) {
+ client.greet("request" + i);
+ }
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+ }
+
+ public void greet(String name) {
+ HelloRequest request = HelloRequest.newBuilder().setName(name).build();
+ HelloReply response;
+ try {
+ response = blockingStub.sayHello(request);
+ } catch (StatusRuntimeException e) {
+ logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
+ return;
+ }
+ logger.info("Greeting: " + response.getMessage());
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveServer.java b/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveServer.java
new file mode 100644
index 00000000000..0a402485906
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/nameresolve/NameResolveServer.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2022 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.examples.nameresolve;
+
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.stub.StreamObserver;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+public class NameResolveServer {
+ static public final int serverCount = 3;
+ static public final int startPort = 50051;
+ private static final Logger logger = Logger.getLogger(NameResolveServer.class.getName());
+ private Server[] servers;
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ final NameResolveServer server = new NameResolveServer();
+ server.start();
+ server.blockUntilShutdown();
+ }
+
+ private void start() throws IOException {
+ servers = new Server[serverCount];
+ for (int i = 0; i < serverCount; i++) {
+ int port = startPort + i;
+ servers[i] = ServerBuilder.forPort(port)
+ .addService(new GreeterImpl(port))
+ .build()
+ .start();
+ logger.info("Server started, listening on " + port);
+ }
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ try {
+ NameResolveServer.this.stop();
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ System.err.println("*** server shut down");
+ }));
+ }
+
+ private void stop() throws InterruptedException {
+ for (int i = 0; i < serverCount; i++) {
+ if (servers[i] != null) {
+ servers[i].shutdown().awaitTermination(30, TimeUnit.SECONDS);
+ }
+ }
+ }
+
+ private void blockUntilShutdown() throws InterruptedException {
+ for (int i = 0; i < serverCount; i++) {
+ if (servers[i] != null) {
+ servers[i].awaitTermination();
+ }
+ }
+ }
+
+ static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
+
+ int port;
+
+ public GreeterImpl(int port) {
+ this.port = port;
+ }
+
+ @Override
+ public void sayHello(HelloRequest req, StreamObserver responseObserver) {
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName() + " from server<" + this.port + ">").build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldClient.java b/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldClient.java
index d8f2e72441b..20c9e5893fb 100644
--- a/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldClient.java
+++ b/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldClient.java
@@ -20,6 +20,8 @@
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
@@ -64,10 +66,8 @@ public class RetryingHelloWorldClient {
*/
public RetryingHelloWorldClient(String host, int port, boolean enableRetries) {
- ManagedChannelBuilder> channelBuilder = ManagedChannelBuilder.forAddress(host, port)
- // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
- // needing certificates.
- .usePlaintext();
+ ManagedChannelBuilder> channelBuilder
+ = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create());
if (enableRetries) {
Map serviceConfig = getRetryingServiceConfig();
logger.info("Client started with retrying configuration: " + serviceConfig);
diff --git a/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldServer.java b/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldServer.java
index 0bff00a6988..165cc72ffa3 100644
--- a/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldServer.java
+++ b/examples/src/main/java/io/grpc/examples/retrying/RetryingHelloWorldServer.java
@@ -19,8 +19,9 @@
import java.text.DecimalFormat;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
-import io.grpc.ServerBuilder;
import io.grpc.Status;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
@@ -43,7 +44,7 @@ public class RetryingHelloWorldServer {
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
- server = ServerBuilder.forPort(port)
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(new GreeterImpl())
.build()
.start();
diff --git a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
index 6958c643da7..f65b1215359 100644
--- a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
+++ b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
@@ -19,8 +19,9 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.Message;
import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.routeguide.RouteGuideGrpc.RouteGuideBlockingStub;
@@ -259,7 +260,8 @@ public static void main(String[] args) throws InterruptedException {
return;
}
- ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
+ .build();
try {
RouteGuideClient client = new RouteGuideClient(channel);
// Looking for a valid feature
diff --git a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
index c91544ae45d..b39b06a6f92 100644
--- a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
+++ b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
@@ -25,6 +25,8 @@
import static java.lang.Math.toRadians;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
@@ -55,7 +57,8 @@ public RouteGuideServer(int port) throws IOException {
/** Create a RouteGuide server listening on {@code port} using {@code featureFile} database. */
public RouteGuideServer(int port, URL featureFile) throws IOException {
- this(ServerBuilder.forPort(port), port, RouteGuideUtil.parseFeatures(featureFile));
+ this(Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create()),
+ port, RouteGuideUtil.parseFeatures(featureFile));
}
/** Create a RouteGuide server using serverBuilder as a base and features as data. */
diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java
index bd11bac8a9c..d04873c5a92 100644
--- a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java
+++ b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java
@@ -1241,7 +1241,7 @@ public void deadlineInPast() throws Exception {
} catch (StatusRuntimeException ex) {
assertEquals(Status.Code.DEADLINE_EXCEEDED, ex.getStatus().getCode());
assertThat(ex.getStatus().getDescription())
- .startsWith("ClientCall started after deadline exceeded");
+ .startsWith("ClientCall started after CallOptions deadline was exceeded");
}
// CensusStreamTracerModule record final status in the interceptor, thus is guaranteed to be
@@ -1274,7 +1274,7 @@ public void deadlineInPast() throws Exception {
} catch (StatusRuntimeException ex) {
assertEquals(Status.Code.DEADLINE_EXCEEDED, ex.getStatus().getCode());
assertThat(ex.getStatus().getDescription())
- .startsWith("ClientCall started after deadline exceeded");
+ .startsWith("ClientCall started after CallOptions deadline was exceeded");
}
if (metricsExpected()) {
MetricsRecord clientStartRecord = clientStatsRecorder.pollRecord(5, TimeUnit.SECONDS);
diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java
index 157fd79524e..eca563fb7c1 100644
--- a/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java
+++ b/interop-testing/src/test/java/io/grpc/testing/integration/RetryTest.java
@@ -351,8 +351,8 @@ public void statsRecorded() throws Exception {
call.request(1);
assertInboundMessageRecorded();
assertInboundWireSizeRecorded(1);
- assertRpcStatusRecorded(Status.Code.OK, 2000, 2);
- assertRetryStatsRecorded(1, 0, 10_000);
+ assertRpcStatusRecorded(Status.Code.OK, 12000, 2);
+ assertRetryStatsRecorded(1, 0, 0);
}
@Test
@@ -410,13 +410,14 @@ public void streamClosed(Status status) {
serverCall.request(2);
assertOutboundWireSizeRecorded(message.length());
fakeClock.forwardTime(7, SECONDS);
- call.cancel("Cancelled before commit", null); // A noop substream will commit.
- // The call listener is closed, but the netty substream listener is not yet closed.
- verify(mockCallListener, timeout(5000)).onClose(any(Status.class), any(Metadata.class));
+ // A noop substream will commit. But call is not yet closed.
+ call.cancel("Cancelled before commit", null);
// Let the netty substream listener be closed.
streamClosedLatch.countDown();
- assertRetryStatsRecorded(1, 0, 10_000);
- assertRpcStatusRecorded(Code.CANCELLED, 7_000, 1);
+ // The call listener is closed.
+ verify(mockCallListener, timeout(5000)).onClose(any(Status.class), any(Metadata.class));
+ assertRpcStatusRecorded(Code.CANCELLED, 17_000, 1);
+ assertRetryStatsRecorded(1, 0, 0);
}
@Test
diff --git a/java_grpc_library.bzl b/java_grpc_library.bzl
index 237fd2fb7a5..11d6e393e98 100644
--- a/java_grpc_library.bzl
+++ b/java_grpc_library.bzl
@@ -30,12 +30,12 @@ java_rpc_toolchain = rule(
providers = [JavaInfo],
),
"plugin": attr.label(
- cfg = "host",
+ cfg = "exec",
executable = True,
),
"plugin_arg": attr.string(),
"_protoc": attr.label(
- cfg = "host",
+ cfg = "exec",
default = Label("@com_google_protobuf//:protoc"),
executable = True,
),
@@ -85,7 +85,7 @@ def _java_rpc_library_impl(ctx):
args = ctx.actions.args()
args.add(toolchain.plugin, format = "--plugin=protoc-gen-rpc-plugin=%s")
args.add("--rpc-plugin_out={0}:{1}".format(toolchain.plugin_arg, srcjar.path))
- args.add_joined("--descriptor_set_in", descriptor_set_in, join_with = ctx.host_configuration.host_path_separator)
+ args.add_joined("--descriptor_set_in", descriptor_set_in, join_with = ctx.configuration.host_path_separator)
args.add_all(srcs, map_each = _path_ignoring_repository)
ctx.actions.run(
diff --git a/netty/BUILD.bazel b/netty/BUILD.bazel
index c1768b61e75..d2497d065ec 100644
--- a/netty/BUILD.bazel
+++ b/netty/BUILD.bazel
@@ -20,20 +20,21 @@ java_library(
"@io_netty_netty_codec_http2//jar",
"@io_netty_netty_codec_socks//jar",
"@io_netty_netty_common//jar",
- "@io_netty_netty_transport_native_unix_common//jar",
"@io_netty_netty_handler//jar",
"@io_netty_netty_handler_proxy//jar",
"@io_netty_netty_resolver//jar",
"@io_netty_netty_transport//jar",
+ "@io_netty_netty_transport_native_unix_common//jar",
"@io_perfmark_perfmark_api//jar",
],
)
# Mirrors the dependencies included in the artifact on Maven Central for usage
-# with maven_install's override_targets. Purposefully does not export any
-# symbols, as it should only be used as a dep for pre-compiled binaries on
-# Maven Central. Not actually shaded; libraries should not be referencing
-# unstable APIs so there should not be any references to the shaded package.
+# with maven_install's override_targets. Should only be used as a dep for
+# pre-compiled binaries on Maven Central.
+#
+# Not actually shaded; libraries should not be referencing unstable APIs so
+# there should not be any references to the shaded package.
java_library(
name = "shaded_maven",
visibility = ["//visibility:public"],
diff --git a/okhttp/build.gradle b/okhttp/build.gradle
index a044503510d..439abaa3373 100644
--- a/okhttp/build.gradle
+++ b/okhttp/build.gradle
@@ -21,6 +21,7 @@ dependencies {
testImplementation project(':grpc-core').sourceSets.test.output,
project(':grpc-api').sourceSets.test.output,
project(':grpc-testing'),
+ project(':grpc-testing-proto'),
libraries.netty.codec.http2,
libraries.okhttp
signature libraries.signature.java
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java
index f0e8bf41ff9..45d6b9efc54 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java
@@ -40,7 +40,10 @@
import io.grpc.internal.SharedResourcePool;
import io.grpc.internal.TransportTracer;
import io.grpc.okhttp.internal.Platform;
+import java.io.IOException;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.Socket;
import java.net.SocketAddress;
import java.security.GeneralSecurityException;
import java.util.EnumSet;
@@ -54,6 +57,8 @@
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
/**
@@ -422,9 +427,26 @@ static HandshakerSocketFactoryResult handshakerSocketFactoryFrom(ServerCredentia
} catch (GeneralSecurityException gse) {
throw new RuntimeException("TLS Provider failure", gse);
}
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+ switch (tlsCreds.getClientAuth()) {
+ case OPTIONAL:
+ sslSocketFactory = new ClientCertRequestingSocketFactory(sslSocketFactory, false);
+ break;
+
+ case REQUIRE:
+ sslSocketFactory = new ClientCertRequestingSocketFactory(sslSocketFactory, true);
+ break;
+
+ case NONE:
+ // NOOP; this is the SSLContext default
+ break;
+
+ default:
+ return HandshakerSocketFactoryResult.error(
+ "Unknown TlsServerCredentials.ClientAuth value: " + tlsCreds.getClientAuth());
+ }
return HandshakerSocketFactoryResult.factory(new TlsServerHandshakerSocketFactory(
- new SslSocketFactoryServerCredentials.ServerCredentials(
- sslContext.getSocketFactory())));
+ new SslSocketFactoryServerCredentials.ServerCredentials(sslSocketFactory)));
} else if (creds instanceof InsecureServerCredentials) {
return HandshakerSocketFactoryResult.factory(new PlaintextHandshakerSocketFactory());
@@ -473,4 +495,59 @@ public static HandshakerSocketFactoryResult factory(HandshakerSocketFactory fact
Preconditions.checkNotNull(factory, "factory"), null);
}
}
+
+ static final class ClientCertRequestingSocketFactory extends SSLSocketFactory {
+ private final SSLSocketFactory socketFactory;
+ private final boolean required;
+
+ public ClientCertRequestingSocketFactory(SSLSocketFactory socketFactory, boolean required) {
+ this.socketFactory = Preconditions.checkNotNull(socketFactory, "socketFactory");
+ this.required = required;
+ }
+
+ private Socket apply(Socket s) throws IOException {
+ if (!(s instanceof SSLSocket)) {
+ throw new IOException(
+ "SocketFactory " + socketFactory + " did not produce an SSLSocket: " + s.getClass());
+ }
+ SSLSocket sslSocket = (SSLSocket) s;
+ if (required) {
+ sslSocket.setNeedClientAuth(true);
+ } else {
+ sslSocket.setWantClientAuth(true);
+ }
+ return sslSocket;
+ }
+
+ @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose)
+ throws IOException {
+ return apply(socketFactory.createSocket(s, host, port, autoClose));
+ }
+
+ @Override public Socket createSocket(String host, int port) throws IOException {
+ return apply(socketFactory.createSocket(host, port));
+ }
+
+ @Override public Socket createSocket(
+ String host, int port, InetAddress localHost, int localPort) throws IOException {
+ return apply(socketFactory.createSocket(host, port, localHost, localPort));
+ }
+
+ @Override public Socket createSocket(InetAddress host, int port) throws IOException {
+ return apply(socketFactory.createSocket(host, port));
+ }
+
+ @Override public Socket createSocket(
+ InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException {
+ return apply(socketFactory.createSocket(host, port, localAddress, localPort));
+ }
+
+ @Override public String[] getDefaultCipherSuites() {
+ return socketFactory.getDefaultCipherSuites();
+ }
+
+ @Override public String[] getSupportedCipherSuites() {
+ return socketFactory.getSupportedCipherSuites();
+ }
+ }
}
diff --git a/okhttp/src/test/java/io/grpc/okhttp/TlsTest.java b/okhttp/src/test/java/io/grpc/okhttp/TlsTest.java
new file mode 100644
index 00000000000..cc86c81d970
--- /dev/null
+++ b/okhttp/src/test/java/io/grpc/okhttp/TlsTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2015 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.okhttp;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.base.Throwables;
+import io.grpc.ChannelCredentials;
+import io.grpc.ConnectivityState;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Server;
+import io.grpc.ServerCredentials;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.TlsChannelCredentials;
+import io.grpc.TlsServerCredentials;
+import io.grpc.internal.testing.TestUtils;
+import io.grpc.stub.StreamObserver;
+import io.grpc.testing.GrpcCleanupRule;
+import io.grpc.testing.TlsTesting;
+import io.grpc.testing.protobuf.SimpleRequest;
+import io.grpc.testing.protobuf.SimpleResponse;
+import io.grpc.testing.protobuf.SimpleServiceGrpc;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Verify OkHttp's TLS integration. */
+@RunWith(JUnit4.class)
+public class TlsTest {
+ @Rule
+ public final GrpcCleanupRule grpcCleanupRule = new GrpcCleanupRule();
+
+ @Before
+ public void checkForAlpnApi() throws Exception {
+ // This checks for the "Java 9 ALPN API" which was backported to Java 8u252. The Kokoro Windows
+ // CI is on too old of a JDK for us to assume this is available.
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, null, null);
+ SSLEngine engine = context.createSSLEngine();
+ try {
+ SSLEngine.class.getMethod("getApplicationProtocol").invoke(engine);
+ } catch (NoSuchMethodException | UnsupportedOperationException ex) {
+ Assume.assumeNoException(ex);
+ }
+ }
+
+ @Test
+ public void mtls_succeeds() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("server1.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .clientAuth(TlsServerCredentials.ClientAuth.REQUIRE)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream clientCertChain = TlsTesting.loadCert("client.pem");
+ InputStream clientPrivateKey = TlsTesting.loadCert("client.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .keyManager(clientCertChain, clientPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannel(server, channelCreds));
+
+ SimpleServiceGrpc.newBlockingStub(channel).unaryRpc(SimpleRequest.getDefaultInstance());
+ }
+
+ @Test
+ public void untrustedClient_fails() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("server1.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .clientAuth(TlsServerCredentials.ClientAuth.REQUIRE)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream clientCertChain = TlsTesting.loadCert("badclient.pem");
+ InputStream clientPrivateKey = TlsTesting.loadCert("badclient.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .keyManager(clientCertChain, clientPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannel(server, channelCreds));
+
+ assertRpcFails(channel);
+ }
+
+ @Test
+ public void missingOptionalClientCert_succeeds() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("server1.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .clientAuth(TlsServerCredentials.ClientAuth.OPTIONAL)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannel(server, channelCreds));
+
+ SimpleServiceGrpc.newBlockingStub(channel).unaryRpc(SimpleRequest.getDefaultInstance());
+ }
+
+ @Test
+ public void missingRequiredClientCert_fails() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("server1.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .clientAuth(TlsServerCredentials.ClientAuth.REQUIRE)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannel(server, channelCreds));
+
+ assertRpcFails(channel);
+ }
+
+ @Test
+ public void untrustedServer_fails() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("badserver.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("badserver.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream clientCertChain = TlsTesting.loadCert("client.pem");
+ InputStream clientPrivateKey = TlsTesting.loadCert("client.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .keyManager(clientCertChain, clientPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannel(server, channelCreds));
+
+ assertRpcFails(channel);
+ }
+
+ @Test
+ public void unmatchedServerSubjectAlternativeNames_fails() throws Exception {
+ ServerCredentials serverCreds;
+ try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
+ InputStream serverPrivateKey = TlsTesting.loadCert("server1.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ serverCreds = TlsServerCredentials.newBuilder()
+ .keyManager(serverCert, serverPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ ChannelCredentials channelCreds;
+ try (InputStream clientCertChain = TlsTesting.loadCert("client.pem");
+ InputStream clientPrivateKey = TlsTesting.loadCert("client.key");
+ InputStream caCert = TlsTesting.loadCert("ca.pem")) {
+ channelCreds = TlsChannelCredentials.newBuilder()
+ .keyManager(clientCertChain, clientPrivateKey)
+ .trustManager(caCert)
+ .build();
+ }
+ Server server = grpcCleanupRule.register(server(serverCreds));
+ ManagedChannel channel = grpcCleanupRule.register(clientChannelBuilder(server, channelCreds)
+ .overrideAuthority("notgonnamatch.example.com")
+ .build());
+
+ assertRpcFails(channel);
+ }
+
+ private static Server server(ServerCredentials creds) throws IOException {
+ return OkHttpServerBuilder.forPort(0, creds)
+ .directExecutor()
+ .addService(new SimpleServiceImpl())
+ .build()
+ .start();
+ }
+
+ private static ManagedChannelBuilder> clientChannelBuilder(
+ Server server, ChannelCredentials creds) {
+ return OkHttpChannelBuilder.forAddress("localhost", server.getPort(), creds)
+ .directExecutor()
+ .overrideAuthority(TestUtils.TEST_SERVER_HOST);
+ }
+
+ private static ManagedChannel clientChannel(Server server, ChannelCredentials creds) {
+ return clientChannelBuilder(server, creds).build();
+ }
+
+ private static void assertRpcFails(ManagedChannel channel) {
+ SimpleServiceGrpc.SimpleServiceBlockingStub stub = SimpleServiceGrpc.newBlockingStub(channel);
+ try {
+ stub.unaryRpc(SimpleRequest.getDefaultInstance());
+ assertWithMessage("TLS handshake should have failed, but didn't; received RPC response")
+ .fail();
+ } catch (StatusRuntimeException e) {
+ assertWithMessage(Throwables.getStackTraceAsString(e))
+ .that(e.getStatus().getCode()).isEqualTo(Status.Code.UNAVAILABLE);
+ }
+ // We really want to see TRANSIENT_FAILURE here, but if the test runs slowly the 1s backoff
+ // may be exceeded by the time the failure happens (since it counts from the start of the
+ // attempt). Even so, CONNECTING is a strong indicator that the handshake failed; otherwise we'd
+ // expect READY or IDLE.
+ assertThat(channel.getState(false))
+ .isAnyOf(ConnectivityState.TRANSIENT_FAILURE, ConnectivityState.CONNECTING);
+ }
+
+ private static final class SimpleServiceImpl extends SimpleServiceGrpc.SimpleServiceImplBase {
+ @Override
+ public void unaryRpc(SimpleRequest req, StreamObserver respOb) {
+ respOb.onNext(SimpleResponse.getDefaultInstance());
+ respOb.onCompleted();
+ }
+ }
+}
diff --git a/services/BUILD.bazel b/services/BUILD.bazel
index 2854b666ba1..f8cc6ad7620 100644
--- a/services/BUILD.bazel
+++ b/services/BUILD.bazel
@@ -3,12 +3,11 @@ load("//:java_grpc_library.bzl", "java_grpc_library")
package(default_visibility = ["//visibility:public"])
# Mirrors the dependencies included in the artifact on Maven Central for usage
-# with maven_install's override_targets. Purposefully does not export any
-# symbols, as it should only be used as a dep for pre-compiled binaries on
-# Maven Central.
+# with maven_install's override_targets. Should only be used as a dep for
+# pre-compiled binaries on Maven Central.
java_library(
name = "services_maven",
- runtime_deps = [
+ exports = [
":admin",
":binarylog",
":channelz",
diff --git a/xds/BUILD.bazel b/xds/BUILD.bazel
index 6e228e636be..e62b183f9e8 100644
--- a/xds/BUILD.bazel
+++ b/xds/BUILD.bazel
@@ -1,13 +1,12 @@
load("//:java_grpc_library.bzl", "java_grpc_library")
# Mirrors the dependencies included in the artifact on Maven Central for usage
-# with maven_install's override_targets. Purposefully does not export any
-# symbols, as it should only be used as a dep for pre-compiled binaries on
-# Maven Central.
+# with maven_install's override_targets. Should only be used as a dep for
+# pre-compiled binaries on Maven Central.
java_library(
name = "xds_maven",
visibility = ["//visibility:public"],
- runtime_deps = [
+ exports = [
":orca",
":xds",
],
diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java
index 2482085adfb..b225b01af7a 100644
--- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java
+++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java
@@ -194,17 +194,7 @@ public void updateBalancingState(ConnectivityState newState, SubchannelPicker ne
@Override
public Subchannel createSubchannel(CreateSubchannelArgs args) {
- List addresses = new ArrayList<>();
- for (EquivalentAddressGroup eag : args.getAddresses()) {
- Attributes.Builder attrBuilder = eag.getAttributes().toBuilder().set(
- InternalXdsAttributes.ATTR_CLUSTER_NAME, cluster);
- if (enableSecurity && sslContextProviderSupplier != null) {
- attrBuilder.set(
- InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER,
- sslContextProviderSupplier);
- }
- addresses.add(new EquivalentAddressGroup(eag.getAddresses(), attrBuilder.build()));
- }
+ List addresses = withAdditionalAttributes(args.getAddresses());
Locality locality = args.getAddresses().get(0).getAttributes().get(
InternalXdsAttributes.ATTR_LOCALITY); // all addresses should be in the same locality
// Endpoint addresses resolved by ClusterResolverLoadBalancer should always contain
@@ -229,6 +219,11 @@ public void shutdown() {
delegate().shutdown();
}
+ @Override
+ public void updateAddresses(List addresses) {
+ delegate().updateAddresses(withAdditionalAttributes(addresses));
+ }
+
@Override
protected Subchannel delegate() {
return subchannel;
@@ -236,6 +231,22 @@ protected Subchannel delegate() {
};
}
+ private List withAdditionalAttributes(
+ List addresses) {
+ List newAddresses = new ArrayList<>();
+ for (EquivalentAddressGroup eag : addresses) {
+ Attributes.Builder attrBuilder = eag.getAttributes().toBuilder().set(
+ InternalXdsAttributes.ATTR_CLUSTER_NAME, cluster);
+ if (enableSecurity && sslContextProviderSupplier != null) {
+ attrBuilder.set(
+ InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER,
+ sslContextProviderSupplier);
+ }
+ newAddresses.add(new EquivalentAddressGroup(eag.getAddresses(), attrBuilder.build()));
+ }
+ return newAddresses;
+ }
+
@Override
protected Helper delegate() {
return helper;
diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
index ca481e5691e..3af58ef93cb 100644
--- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
+++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
@@ -216,7 +216,6 @@ private void handleEndpointResourceUpdate() {
List addresses = new ArrayList<>();
Map priorityChildConfigs = new HashMap<>();
List priorities = new ArrayList<>(); // totally ordered priority list
- Map localityWeights = new HashMap<>();
Status endpointNotFound = Status.OK;
for (String cluster : clusters) {
@@ -229,7 +228,6 @@ private void handleEndpointResourceUpdate() {
addresses.addAll(state.result.addresses);
priorityChildConfigs.putAll(state.result.priorityChildConfigs);
priorities.addAll(state.result.priorities);
- localityWeights.putAll(state.result.localityWeights);
} else {
endpointNotFound = state.status;
}
@@ -260,9 +258,6 @@ private void handleEndpointResourceUpdate() {
resolvedAddresses.toBuilder()
.setLoadBalancingPolicyConfig(childConfig)
.setAddresses(Collections.unmodifiableList(addresses))
- .setAttributes(resolvedAddresses.getAttributes().toBuilder()
- .set(InternalXdsAttributes.ATTR_LOCALITY_WEIGHTS,
- Collections.unmodifiableMap(localityWeights)).build())
.build());
}
@@ -396,7 +391,6 @@ public void run() {
}
Map localityLbEndpoints =
update.localityLbEndpointsMap;
- Map localityWeights = new HashMap<>();
List dropOverloads = update.dropPolicies;
List addresses = new ArrayList<>();
Map> prioritizedLocalityWeights = new HashMap<>();
@@ -415,6 +409,8 @@ public void run() {
Attributes attr =
endpoint.eag().getAttributes().toBuilder()
.set(InternalXdsAttributes.ATTR_LOCALITY, locality)
+ .set(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT,
+ localityLbInfo.localityWeight())
.set(InternalXdsAttributes.ATTR_SERVER_WEIGHT, weight)
.build();
EquivalentAddressGroup eag = new EquivalentAddressGroup(
@@ -429,7 +425,6 @@ public void run() {
"Discard locality {0} with 0 healthy endpoints", locality);
continue;
}
- localityWeights.put(locality, localityLbInfo.localityWeight());
if (!prioritizedLocalityWeights.containsKey(priorityName)) {
prioritizedLocalityWeights.put(priorityName, new HashMap());
}
@@ -450,7 +445,7 @@ public void run() {
status = Status.OK;
resolved = true;
result = new ClusterResolutionResult(addresses, priorityChildConfigs,
- sortedPriorityNames, localityWeights);
+ sortedPriorityNames);
handleEndpointResourceUpdate();
}
}
@@ -690,23 +685,18 @@ private static class ClusterResolutionResult {
private final Map priorityChildConfigs;
// List of priority names ordered in descending priorities.
private final List priorities;
- // Most recent view on how localities in the cluster should be wighted. Only set for EDS
- // clusters that support the concept.
- private final Map localityWeights;
ClusterResolutionResult(List addresses, String priority,
PriorityChildConfig config) {
this(addresses, Collections.singletonMap(priority, config),
- Collections.singletonList(priority), Collections.emptyMap());
+ Collections.singletonList(priority));
}
ClusterResolutionResult(List addresses,
- Map configs, List priorities,
- Map localityWeights) {
+ Map configs, List priorities) {
this.addresses = addresses;
this.priorityChildConfigs = configs;
this.priorities = priorities;
- this.localityWeights = localityWeights;
}
}
diff --git a/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java b/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java
index 448e5fbd258..bd21a8ac13e 100644
--- a/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java
+++ b/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java
@@ -24,7 +24,6 @@
import io.grpc.internal.ObjectPool;
import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider;
import io.grpc.xds.internal.security.SslContextProviderSupplier;
-import java.util.Map;
/**
* Internal attributes used for xDS implementation. Do not use.
@@ -58,8 +57,8 @@ public final class InternalXdsAttributes {
* Map from localities to their weights.
*/
@NameResolver.ResolutionResultAttr
- static final Attributes.Key