Skip to content

Commit

Permalink
netty: Add ServerCredentials
Browse files Browse the repository at this point in the history
  • Loading branch information
ejona86 committed Nov 13, 2020
1 parent 60319da commit edcc685
Show file tree
Hide file tree
Showing 13 changed files with 522 additions and 59 deletions.
Expand Up @@ -21,9 +21,11 @@
import io.grpc.ChannelCredentials;
import io.grpc.Grpc;
import io.grpc.InsecureChannelCredentials;
import io.grpc.InsecureServerCredentials;
import io.grpc.ManagedChannel;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.ServerCredentials;
import io.grpc.TlsServerCredentials;
import io.grpc.internal.testing.TestUtils;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
Expand Down Expand Up @@ -69,14 +71,15 @@ public void noNormalNetty() throws Exception {

@Test
public void serviceLoaderFindsNetty() throws Exception {
assertThat(ServerBuilder.forPort(0)).isInstanceOf(NettyServerBuilder.class);
assertThat(Grpc.newServerBuilderForPort(0, InsecureServerCredentials.create()))
.isInstanceOf(NettyServerBuilder.class);
assertThat(Grpc.newChannelBuilder("localhost:1234", InsecureChannelCredentials.create()))
.isInstanceOf(NettyChannelBuilder.class);
}

@Test
public void basic() throws Exception {
server = ServerBuilder.forPort(0)
server = Grpc.newServerBuilderForPort(0, InsecureServerCredentials.create())
.addService(new SimpleServiceImpl())
.build().start();
channel = Grpc.newChannelBuilder(
Expand All @@ -89,8 +92,9 @@ public void basic() throws Exception {

@Test
public void tcnative() throws Exception {
server = NettyServerBuilder.forPort(0)
.useTransportSecurity(TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key"))
ServerCredentials serverCreds = TlsServerCredentials.create(
TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key"));
server = Grpc.newServerBuilderForPort(0, serverCreds)
.addService(new SimpleServiceImpl())
.build().start();
ChannelCredentials creds = NettySslContextChannelCredentials.create(
Expand Down
Expand Up @@ -18,8 +18,6 @@

import io.grpc.ChannelCredentials;
import io.grpc.Internal;
import io.netty.channel.ChannelHandler;
import io.netty.util.AsciiString;

/**
* Internal {@link NettyChannelCredentials} accessor. This is intended for usage internal to the
Expand Down Expand Up @@ -50,27 +48,8 @@ final class ClientFactory implements InternalProtocolNegotiator.ClientFactory {

@Override
public InternalProtocolNegotiator.ProtocolNegotiator newNegotiator() {
final ProtocolNegotiator pn = result.negotiator.newNegotiator();
final class LocalProtocolNegotiator
implements InternalProtocolNegotiator.ProtocolNegotiator {

@Override
public AsciiString scheme() {
return pn.scheme();
}

@Override
public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) {
return pn.newHandler(grpcHandler);
}

@Override
public void close() {
pn.close();
}
}

return new LocalProtocolNegotiator();
return new InternalProtocolNegotiator.ProtocolNegotiatorAdapter(
result.negotiator.newNegotiator());
}

@Override
Expand Down
@@ -0,0 +1,69 @@
/*
* 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.netty;

import io.grpc.Internal;
import io.grpc.ServerCredentials;
import io.grpc.internal.ObjectPool;
import java.util.concurrent.Executor;

/**
* Internal {@link NettyServerCredentials} accessor. This is intended for usage internal to the
* gRPC team. If you *really* think you need to use this, contact the gRPC team first.
*/
@Internal
public final class InternalNettyServerCredentials {
private InternalNettyServerCredentials() {}

/** Creates a {@link ServerCredentials} that will use the provided {@code negotiator}. */
public static ServerCredentials create(InternalProtocolNegotiator.ProtocolNegotiator negotiator) {
return NettyServerCredentials.create(ProtocolNegotiators.fixedServerFactory(negotiator));
}

/**
* Creates a {@link ServerCredentials} that will use the provided {@code negotiator}. Use of
* {@link #create(io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator)} is preferred over
* this method when possible.
*/
public static ServerCredentials create(InternalProtocolNegotiator.ServerFactory negotiator) {
return NettyServerCredentials.create(negotiator);
}

/**
* Converts a {@link ServerCredentials} to a negotiator, in similar fashion as for a new server.
*
* @throws IllegalArgumentException if unable to convert
*/
public static InternalProtocolNegotiator.ServerFactory toNegotiator(
ServerCredentials channelCredentials) {
final ProtocolNegotiators.FromServerCredentialsResult result =
ProtocolNegotiators.from(channelCredentials);
if (result.error != null) {
throw new IllegalArgumentException(result.error);
}
final class ServerFactory implements InternalProtocolNegotiator.ServerFactory {
@Override
public InternalProtocolNegotiator.ProtocolNegotiator newNegotiator(
ObjectPool<? extends Executor> offloadExecutorPool) {
return new InternalProtocolNegotiator.ProtocolNegotiatorAdapter(
result.negotiator.newNegotiator(offloadExecutorPool));
}
}

return new ServerFactory();
}
}
33 changes: 33 additions & 0 deletions netty/src/main/java/io/grpc/netty/InternalProtocolNegotiator.java
Expand Up @@ -16,7 +16,12 @@

package io.grpc.netty;

import com.google.common.base.Preconditions;
import io.grpc.Internal;
import io.grpc.internal.ObjectPool;
import io.netty.channel.ChannelHandler;
import io.netty.util.AsciiString;
import java.util.concurrent.Executor;

/**
* Internal accessor for {@link ProtocolNegotiator}.
Expand All @@ -28,7 +33,35 @@ private InternalProtocolNegotiator() {}

public interface ProtocolNegotiator extends io.grpc.netty.ProtocolNegotiator {}

static final class ProtocolNegotiatorAdapter
implements InternalProtocolNegotiator.ProtocolNegotiator {
private final io.grpc.netty.ProtocolNegotiator negotiator;

public ProtocolNegotiatorAdapter(io.grpc.netty.ProtocolNegotiator negotiator) {
this.negotiator = Preconditions.checkNotNull(negotiator, "negotiator");
}

@Override
public AsciiString scheme() {
return negotiator.scheme();
}

@Override
public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) {
return negotiator.newHandler(grpcHandler);
}

@Override
public void close() {
negotiator.close();
}
}

public interface ClientFactory extends io.grpc.netty.ProtocolNegotiator.ClientFactory {
@Override ProtocolNegotiator newNegotiator();
}

public interface ServerFactory extends io.grpc.netty.ProtocolNegotiator.ServerFactory {
@Override ProtocolNegotiator newNegotiator(ObjectPool<? extends Executor> offloadExecutorPool);
}
}
80 changes: 59 additions & 21 deletions netty/src/main/java/io/grpc/netty/NettyServerBuilder.java
Expand Up @@ -29,6 +29,7 @@
import io.grpc.ExperimentalApi;
import io.grpc.Internal;
import io.grpc.ServerBuilder;
import io.grpc.ServerCredentials;
import io.grpc.ServerStreamTracer;
import io.grpc.internal.AbstractServerImplBuilder;
import io.grpc.internal.FixedObjectPool;
Expand Down Expand Up @@ -58,7 +59,6 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.net.ssl.SSLException;

/**
Expand Down Expand Up @@ -98,8 +98,8 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
private ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool =
DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
private boolean forceHeapBuffer;
private SslContext sslContext;
private ProtocolNegotiator protocolNegotiator;
private ProtocolNegotiator.ServerFactory protocolNegotiatorFactory;
private final boolean freezeProtocolNegotiatorFactory;
private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE;
private boolean autoFlowControl = true;
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
Expand All @@ -121,7 +121,18 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
*/
@CheckReturnValue
public static NettyServerBuilder forPort(int port) {
return new NettyServerBuilder(port);
return forAddress(new InetSocketAddress(port));
}

/**
* Creates a server builder that will bind to the given port.
*
* @param port the port on which the server is to be bound.
* @return the server builder.
*/
@CheckReturnValue
public static NettyServerBuilder forPort(int port, ServerCredentials creds) {
return forAddress(new InetSocketAddress(port), creds);
}

/**
Expand All @@ -135,6 +146,21 @@ public static NettyServerBuilder forAddress(SocketAddress address) {
return new NettyServerBuilder(address);
}

/**
* Creates a server builder configured with the given {@link SocketAddress}.
*
* @param address the socket address on which the server is to be bound.
* @return the server builder
*/
@CheckReturnValue
public static NettyServerBuilder forAddress(SocketAddress address, ServerCredentials creds) {
ProtocolNegotiators.FromServerCredentialsResult result = ProtocolNegotiators.from(creds);
if (result.error != null) {
throw new IllegalArgumentException(result.error);
}
return new NettyServerBuilder(address, result.negotiator);
}

private final class NettyClientTransportServersBuilder implements ClientTransportServersBuilder {
@Override
public List<? extends InternalServer> buildClientTransportServers(
Expand All @@ -144,15 +170,20 @@ public List<? extends InternalServer> buildClientTransportServers(
}

@CheckReturnValue
private NettyServerBuilder(int port) {
private NettyServerBuilder(SocketAddress address) {
serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
this.listenAddresses.add(new InetSocketAddress(port));
this.listenAddresses.add(address);
this.protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
this.freezeProtocolNegotiatorFactory = false;
}

@CheckReturnValue
private NettyServerBuilder(SocketAddress address) {
NettyServerBuilder(
SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory) {
serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
this.listenAddresses.add(address);
this.protocolNegotiatorFactory = checkNotNull(negotiatorFactory, "negotiatorFactory");
this.freezeProtocolNegotiatorFactory = true;
}

@Internal
Expand Down Expand Up @@ -317,25 +348,28 @@ void setForceHeapBuffer(boolean value) {
* have been configured with {@link GrpcSslContexts}, but options could have been overridden.
*/
public NettyServerBuilder sslContext(SslContext sslContext) {
checkState(!freezeProtocolNegotiatorFactory,
"Cannot change security when using ServerCredentials");
if (sslContext != null) {
checkArgument(sslContext.isServer(),
"Client SSL context can not be used for server");
GrpcSslContexts.ensureAlpnAndH2Enabled(sslContext.applicationProtocolNegotiator());
protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
} else {
protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
}
this.sslContext = sslContext;
return this;
}

/**
* Sets the {@link ProtocolNegotiator} to be used. If non-{@code null}, overrides the value
* specified in {@link #sslContext(SslContext)}.
*
* <p>Default: {@code null}.
* Sets the {@link ProtocolNegotiator} to be used. Overrides the value specified in {@link
* #sslContext(SslContext)}.
*/
@Internal
public final NettyServerBuilder protocolNegotiator(
@Nullable ProtocolNegotiator protocolNegotiator) {
this.protocolNegotiator = protocolNegotiator;
public final NettyServerBuilder protocolNegotiator(ProtocolNegotiator protocolNegotiator) {
checkState(!freezeProtocolNegotiatorFactory,
"Cannot change security when using ServerCredentials");
this.protocolNegotiatorFactory = ProtocolNegotiators.fixedServerFactory(protocolNegotiator);
return this;
}

Expand Down Expand Up @@ -586,12 +620,8 @@ List<NettyServer> buildTransportServers(
List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
assertEventLoopsAndChannelType();

ProtocolNegotiator negotiator = protocolNegotiator;
if (negotiator == null) {
negotiator = sslContext != null
? ProtocolNegotiators.serverTls(sslContext, this.serverImplBuilder.getExecutorPool())
: ProtocolNegotiators.serverPlaintext();
}
ProtocolNegotiator negotiator = protocolNegotiatorFactory.newNegotiator(
this.serverImplBuilder.getExecutorPool());

List<NettyServer> transportServers = new ArrayList<>(listenAddresses.size());
for (SocketAddress listenAddress : listenAddresses) {
Expand Down Expand Up @@ -631,23 +661,31 @@ NettyServerBuilder setTransportTracerFactory(

@Override
public NettyServerBuilder useTransportSecurity(File certChain, File privateKey) {
checkState(!freezeProtocolNegotiatorFactory,
"Cannot change security when using ServerCredentials");
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
} catch (SSLException e) {
// This should likely be some other, easier to catch exception.
throw new RuntimeException(e);
}
protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
return this;
}

@Override
public NettyServerBuilder useTransportSecurity(InputStream certChain, InputStream privateKey) {
checkState(!freezeProtocolNegotiatorFactory,
"Cannot change security when using ServerCredentials");
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
} catch (SSLException e) {
// This should likely be some other, easier to catch exception.
throw new RuntimeException(e);
}
protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
return this;
}
}

0 comments on commit edcc685

Please sign in to comment.