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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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;
}
}
Loading

0 comments on commit edcc685

Please sign in to comment.