// Copyright 2017 The Nomulus Authors. All Rights Reserved. // // 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 google.registry.proxy; import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.Attribute; import io.netty.util.AttributeKey; import javax.annotation.Nullable; import javax.inject.Provider; /** Value class that encapsulates parameters of a specific connection. */ public interface Protocol { /** Key used to retrieve the {@link Protocol} from a {@link Channel}'s {@link Attribute}. */ AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); /** Protocol name. */ String name(); /** * Port to bind to (for {@link FrontendProtocol}) or to connect to (for {@link BackendProtocol}). */ int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ ImmutableList> handlerProviders(); /** * A builder for {@link FrontendProtocol}, default is non-health-checking. * * @see HealthCheckProtocolModule */ static FrontendProtocol.Builder frontendBuilder() { return new AutoValue_Protocol_FrontendProtocol.Builder().isHealthCheck(false); } static BackendProtocol.Builder backendBuilder() { return new AutoValue_Protocol_BackendProtocol.Builder(); } /** * Generic builder enabling chaining for concrete implementations. * * @param builder of the concrete subtype of {@link Protocol}. * @param

type of the concrete subtype of {@link Protocol}. */ abstract class Builder, P extends Protocol> { public abstract B name(String value); public abstract B port(int port); public abstract B handlerProviders(ImmutableList> value); public abstract P build(); } /** * Connection parameters for a connection from the client to the proxy. * *

This protocol is associated to a {@link NioSocketChannel} established by remote peer * connecting to the given {@code port} that the proxy is listening on. */ @AutoValue abstract class FrontendProtocol implements Protocol { /** * The {@link BackendProtocol} used to establish a relay channel and relay the traffic to. Not * required for health check protocol. */ @Nullable public abstract BackendProtocol relayProtocol(); public abstract boolean isHealthCheck(); @AutoValue.Builder public abstract static class Builder extends Protocol.Builder { public abstract Builder relayProtocol(BackendProtocol value); public abstract Builder isHealthCheck(boolean value); abstract FrontendProtocol autoBuild(); @Override public FrontendProtocol build() { FrontendProtocol frontendProtocol = autoBuild(); Preconditions.checkState( frontendProtocol.isHealthCheck() || frontendProtocol.relayProtocol() != null, "Frontend protocol %s must define a relay protocol.", frontendProtocol.name()); return frontendProtocol; } } } /** * Connection parameters for a connection from the proxy to the GAE app. * *

This protocol is associated to a {@link NioSocketChannel} established by the proxy * connecting to a remote peer. */ @AutoValue abstract class BackendProtocol implements Protocol { /** The hostname that the proxy connects to. */ public abstract String host(); /** Builder of {@link BackendProtocol}. */ @AutoValue.Builder public abstract static class Builder extends Protocol.Builder { public abstract Builder host(String value); } } }